Browse Source

Fixed tests, fixed compilation, added DHT marker decoding more meaningful exception messages, fixed invalid jpeg encoding

pull/1761/head
Dmitry Pentin 5 years ago
parent
commit
775610d5a0
  1. 22
      src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs
  2. 4
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  3. 20
      tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs

22
src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs

@ -561,13 +561,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
/// this method endianness dependent.
/// </remarks>
[MethodImpl(InliningOptions.ShortMethod)]
private void FlushToStream()
private void FlushToStream(int endIndex)
{
Span<byte> emitBytes = MemoryMarshal.AsBytes(this.emitBuffer.AsSpan());
int writeIdx = 0;
int startIndex = emitBytes.Length - 1;
int endIndex = this.emitWriteIndex * sizeof(uint);
// Some platforms may fail to eliminate this if-else branching
// Even if it happens - buffer is flushed in big packs,
@ -621,28 +620,25 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
}
this.target.Write(this.streamWriteBuffer, 0, writeIdx);
}
private void FlushToStream()
{
this.FlushToStream(this.emitWriteIndex * 4);
this.emitWriteIndex = this.emitBuffer.Length;
}
[MethodImpl(InliningOptions.ShortMethod)]
private void FlushRemainingBytes()
{
// Flush full 4-byte blocks
this.FlushToStream();
// Padding all 4 bytes with 1's while not corrupting initial bits stored in accumulatedBits
// And writing only valuable count of bytes count we want to write to the output stream
int valuableBytesCount = (int)Numerics.DivideCeil((uint)this.bitCount, 8);
uint packedBytes = this.accumulatedBits | (uint.MaxValue >> this.bitCount);
this.emitBuffer[--this.emitWriteIndex] = packedBytes;
Span<byte> emitBytes = MemoryMarshal.AsBytes(this.emitBuffer.AsSpan());
for (int i = 0; i < valuableBytesCount; i++)
{
emitBytes[i] = (byte)((packedBytes >> ((3 - i) * 8)) & 0xff);
}
// Flush remaining 'tail' bytes
this.target.Write(emitBytes, 0, valuableBytesCount);
// Flush cached bytes to the output stream with padding bits
this.FlushToStream((this.emitWriteIndex * 4) - 4 + valuableBytesCount);
}
}
}

4
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -1071,13 +1071,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// Types 0..1 DC..AC
if (tableType > 1)
{
JpegThrowHelper.ThrowInvalidImageContentException("Bad Huffman Table type.");
JpegThrowHelper.ThrowInvalidImageContentException($"Bad huffman table type: {tableType}");
}
// Max tables of each type
if (tableIndex > 3)
{
JpegThrowHelper.ThrowInvalidImageContentException("Bad Huffman Table index.");
JpegThrowHelper.ThrowInvalidImageContentException($"Bad huffman table index: {tableIndex}");
}
stream.Read(huffmanDataSpan, 0, 16);

20
tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs

@ -2,9 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics.X86;
#endif
@ -121,24 +118,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void IDCT8x8_Avx(int seed)
{
#if SUPPORTS_RUNTIME_INTRINSICS
var skip = !Avx.IsSupported;
#else
var skip = true;
#endif
if (skip)
if (!Avx.IsSupported)
{
this.Output.WriteLine("No AVX present, skipping test!");
return;
}
Span<float> src = Create8x8RoundedRandomFloatData(-200, 200, seed);
var srcBlock = default(Block8x8F);
Block8x8F srcBlock = default;
srcBlock.LoadFrom(src);
var destBlock = default(Block8x8F);
Block8x8F destBlock = default;
var expectedDest = new float[64];
float[] expectedDest = new float[64];
// reference, left part
ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D8x4_32f(src, expectedDest);
@ -149,10 +140,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
// testee, whole 8x8
FastFloatingPointDCT.IDCT8x8_Avx(ref srcBlock, ref destBlock);
var actualDest = new float[64];
float[] actualDest = new float[64];
destBlock.ScaledCopyTo(actualDest);
Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
#endif
}
[Theory]

Loading…
Cancel
Save