Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify jpeg encoder and fix for Windows ARM #1304

Merged
merged 13 commits into from
Aug 7, 2020
Merged
26 changes: 15 additions & 11 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@

<!--
https://apisof.net/
+===================+=======+==========+=====================+=============+=================+====================+==============+=========+
| SUPPORTS | MATHF | HASHCODE | EXTENDED_INTRINSICS | SPAN_STREAM | ENCODING_STRING | RUNTIME_INTRINSICS | CODECOVERAGE | HOTPATH |
+===================+=======+==========+=====================+=============+=================+====================+==============+=========|
| netcoreapp3.1 | Y | Y | Y | Y | Y | Y | Y | Y |
| netcoreapp2.1 | Y | Y | Y | Y | Y | N | Y | N |
| netcoreapp2.0 | Y | N | N | N | N | N | Y | N |
| netstandard2.1 | Y | Y | N | Y | Y | N | Y | N |
| netstandard2.0 | N | N | N | N | N | N | Y | N |
| netstandard1.3 | N | N | N | N | N | N | N | N |
| net472 | N | N | Y | N | N | N | Y | N |
+===================+=======+==========+=====================+=============+=================+====================+==============+=========|
+===================+=======+==========+=====================+=============+=================+====================+==============+=========+============|
| SUPPORTS | MATHF | HASHCODE | EXTENDED_INTRINSICS | SPAN_STREAM | ENCODING_STRING | RUNTIME_INTRINSICS | CODECOVERAGE | HOTPATH | CREATESPAN |
+===================+=======+==========+=====================+=============+=================+====================+==============+=========|============|
| netcoreapp3.1 | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| netcoreapp2.1 | Y | Y | Y | Y | Y | N | Y | N | Y |
| netcoreapp2.0 | Y | N | N | N | N | N | Y | N | Y |
| netstandard2.1 | Y | Y | N | Y | Y | N | Y | N | Y |
| netstandard2.0 | N | N | N | N | N | N | Y | N | N |
| netstandard1.3 | N | N | N | N | N | N | N | N | N |
| net472 | N | N | Y | N | N | N | Y | N | N |
+===================+=======+==========+=====================+=============+=================+====================+==============+=========|============|
-->

<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
Expand All @@ -52,6 +52,7 @@
<DefineConstants>$(DefineConstants);SUPPORTS_RUNTIME_INTRINSICS</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_HOTPATH</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CREATESPAN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<DefineConstants>$(DefineConstants);SUPPORTS_MATHF</DefineConstants>
Expand All @@ -60,17 +61,20 @@
<DefineConstants>$(DefineConstants);SUPPORTS_SPAN_STREAM</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_ENCODING_STRING</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CREATESPAN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<DefineConstants>$(DefineConstants);SUPPORTS_MATHF</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CREATESPAN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
<DefineConstants>$(DefineConstants);SUPPORTS_MATHF</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_HASHCODE</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_SPAN_STREAM</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_ENCODING_STRING</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CREATESPAN</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
Expand Down
27 changes: 11 additions & 16 deletions src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,45 +376,40 @@ public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr,
/// <param name="block">Source block</param>
/// <param name="dest">Destination block</param>
/// <param name="qt">The quantization table</param>
/// <param name="unzigPtr">Pointer to elements of <see cref="ZigZag"/></param>
/// <param name="unZig">The 8x8 Unzig block.</param>
public static unsafe void Quantize(
Block8x8F* block,
Block8x8F* dest,
Block8x8F* qt,
byte* unzigPtr)
ref Block8x8F block,
ref Block8x8F dest,
ref Block8x8F qt,
ref ZigZag unZig)
{
float* s = (float*)block;
float* d = (float*)dest;

for (int zig = 0; zig < Size; zig++)
{
d[zig] = s[unzigPtr[zig]];
dest[zig] = block[unZig[zig]];
}

DivideRoundAll(ref *dest, ref *qt);
DivideRoundAll(ref dest, ref qt);
}

/// <summary>
/// Scales the 16x16 region represented by the 4 source blocks to the 8x8 DST block.
/// </summary>
/// <param name="destination">The destination block.</param>
/// <param name="source">The source block.</param>
public static unsafe void Scale16X16To8X8(Block8x8F* destination, Block8x8F* source)
public static unsafe void Scale16X16To8X8(ref Block8x8F destination, ReadOnlySpan<Block8x8F> source)
{
float* d = (float*)destination;
for (int i = 0; i < 4; i++)
{
int dstOff = ((i & 2) << 4) | ((i & 1) << 2);

float* iSource = (float*)(source + i);
Block8x8F iSource = source[i];

for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
int j = (16 * y) + (2 * x);
float sum = iSource[j] + iSource[j + 1] + iSource[j + 8] + iSource[j + 9];
d[(8 * y) + x + dstOff] = (sum + 2) / 4;
destination[(8 * y) + x + dstOff] = (sum + 2) * .25F;
}
}
}
Expand Down Expand Up @@ -589,7 +584,7 @@ private static Vector<float> NormalizeAndRound(Vector<float> row, Vector<float>
private static Vector4 DivideRound(Vector4 dividend, Vector4 divisor)
{
// sign(dividend) = max(min(dividend, 1), -1)
var sign = Vector4Utilities.FastClamp(dividend, NegativeOne, Vector4.One);
Vector4 sign = Vector4Utilities.FastClamp(dividend, NegativeOne, Vector4.One);

// AlmostRound(dividend/divisor) = dividend/divisor + 0.5*sign(dividend)
return (dividend / divisor) + (sign * Offset);
Expand Down
17 changes: 0 additions & 17 deletions src/ImageSharp/Formats/Jpeg/Components/Encoder/BlockQuad.cs

This file was deleted.

37 changes: 17 additions & 20 deletions src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrTables.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -96,30 +96,27 @@ public static RgbToYCbCrTables Create()
/// Optimized method to allocates the correct y, cb, and cr values to the DCT blocks from the given r, g, b values.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ConvertPixelInto(int r, int g, int b, ref float yResult, ref float cbResult, ref float crResult)
public void ConvertPixelInto(
int r,
int g,
int b,
ref Block8x8F yResult,
ref Block8x8F cbResult,
ref Block8x8F crResult,
int i)
{
ref int start = ref Unsafe.As<RgbToYCbCrTables, int>(ref this);
// float y = (0.299F * r) + (0.587F * g) + (0.114F * b);
yResult[i] = (this.YRTable[r] + this.YGTable[g] + this.YBTable[b]) >> ScaleBits;

ref int yR = ref start;
ref int yG = ref Unsafe.Add(ref start, 256 * 1);
ref int yB = ref Unsafe.Add(ref start, 256 * 2);
// float cb = 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b));
cbResult[i] = (this.CbRTable[r] + this.CbGTable[g] + this.CbBTable[b]) >> ScaleBits;

ref int cbR = ref Unsafe.Add(ref start, 256 * 3);
ref int cbG = ref Unsafe.Add(ref start, 256 * 4);
ref int cbB = ref Unsafe.Add(ref start, 256 * 5);

ref int crG = ref Unsafe.Add(ref start, 256 * 6);
ref int crB = ref Unsafe.Add(ref start, 256 * 7);

yResult = (Unsafe.Add(ref yR, r) + Unsafe.Add(ref yG, g) + Unsafe.Add(ref yB, b)) >> ScaleBits;
cbResult = (Unsafe.Add(ref cbR, r) + Unsafe.Add(ref cbG, g) + Unsafe.Add(ref cbB, b)) >> ScaleBits;
crResult = (Unsafe.Add(ref cbB, r) + Unsafe.Add(ref crG, g) + Unsafe.Add(ref crB, b)) >> ScaleBits;
// float cr = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero);
crResult[i] = (this.CbBTable[r] + this.CrGTable[g] + this.CrBTable[b]) >> ScaleBits;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int Fix(float x)
{
return (int)((x * (1L << ScaleBits)) + 0.5F);
}
=> (int)((x * (1L << ScaleBits)) + 0.5F);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ public void Convert(ImageFrame<TPixel> frame, int x, int y, in RowOctet<TPixel>
Span<Rgb24> rgbSpan = this.rgbBlock.AsSpanUnsafe();
PixelOperations<TPixel>.Instance.ToRgb24(frame.GetConfiguration(), this.pixelBlock.AsSpanUnsafe(), rgbSpan);

ref float yBlockStart = ref Unsafe.As<Block8x8F, float>(ref this.Y);
ref float cbBlockStart = ref Unsafe.As<Block8x8F, float>(ref this.Cb);
ref float crBlockStart = ref Unsafe.As<Block8x8F, float>(ref this.Cr);
ref Block8x8F yBlock = ref this.Y;
ref Block8x8F cbBlock = ref this.Cb;
ref Block8x8F crBlock = ref this.Cr;
ref Rgb24 rgbStart = ref rgbSpan[0];

for (int i = 0; i < 64; i++)
Expand All @@ -75,9 +75,10 @@ public void Convert(ImageFrame<TPixel> frame, int x, int y, in RowOctet<TPixel>
c.R,
c.G,
c.B,
ref Unsafe.Add(ref yBlockStart, i),
ref Unsafe.Add(ref cbBlockStart, i),
ref Unsafe.Add(ref crBlockStart, i));
ref yBlock,
ref cbBlock,
ref crBlock,
i);
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions src/ImageSharp/Formats/Jpeg/Components/GenericBlock8x8.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;

Expand All @@ -16,7 +15,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct GenericBlock8x8<T>
where T : struct
where T : unmanaged
{
public const int Size = 64;

Expand Down Expand Up @@ -110,6 +109,14 @@ public void LoadAndStretchEdges(Buffer2D<T> source, int sourceX, int sourceY, in
/// <summary>
/// Only for on-stack instances!
/// </summary>
public Span<T> AsSpanUnsafe() => new Span<T>(Unsafe.AsPointer(ref this), Size);
public Span<T> AsSpanUnsafe()
{
#if SUPPORTS_CREATESPAN
Span<GenericBlock8x8<T>> s = MemoryMarshal.CreateSpan(ref this, 1);
return MemoryMarshal.Cast<GenericBlock8x8<T>, T>(s);
#else
return new Span<T>(Unsafe.AsPointer(ref this), Size);
#endif
}
}
}
Loading