Browse Source

Add test for ICCP

pull/2109/head
Brian Popow 4 years ago
parent
commit
5bac8b36bf
  1. 8
      src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs
  2. 10
      src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs
  3. 10
      src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs
  4. 31
      tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs

8
src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs

@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
} }
/// <summary> /// <summary>
/// Calculates the chunk size of EXIF or XMP metadata. /// Calculates the chunk size of EXIF, XMP or ICCP metadata.
/// </summary> /// </summary>
/// <param name="metadataBytes">The metadata profile bytes.</param> /// <param name="metadataBytes">The metadata profile bytes.</param>
/// <returns>The metadata chunk size in bytes.</returns> /// <returns>The metadata chunk size in bytes.</returns>
@ -209,11 +209,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
/// <param name="stream">The stream to write to.</param> /// <param name="stream">The stream to write to.</param>
/// <param name="exifProfile">A exif profile or null, if it does not exist.</param> /// <param name="exifProfile">A exif profile or null, if it does not exist.</param>
/// <param name="xmpProfile">A XMP profile or null, if it does not exist.</param> /// <param name="xmpProfile">A XMP profile or null, if it does not exist.</param>
/// <param name="iccProfile">The color profile.</param> /// <param name="iccProfileBytes">The color profile bytes.</param>
/// <param name="width">The width of the image.</param> /// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param> /// <param name="height">The height of the image.</param>
/// <param name="hasAlpha">Flag indicating, if a alpha channel is present.</param> /// <param name="hasAlpha">Flag indicating, if a alpha channel is present.</param>
protected void WriteVp8XHeader(Stream stream, ExifProfile exifProfile, XmpProfile xmpProfile, IccProfile iccProfile, uint width, uint height, bool hasAlpha) protected void WriteVp8XHeader(Stream stream, ExifProfile exifProfile, XmpProfile xmpProfile, byte[] iccProfileBytes, uint width, uint height, bool hasAlpha)
{ {
if (width > MaxDimension || height > MaxDimension) if (width > MaxDimension || height > MaxDimension)
{ {
@ -245,7 +245,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
flags |= 16; flags |= 16;
} }
if (iccProfile != null) if (iccProfileBytes != null)
{ {
// Set iccp flag. // Set iccp flag.
flags |= 32; flags |= 32;

10
src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs

@ -481,7 +481,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
riffSize += WebpConstants.TagSize + WebpConstants.ChunkHeaderSize + vp8Size; riffSize += WebpConstants.TagSize + WebpConstants.ChunkHeaderSize + vp8Size;
// Emit headers and partition #0 // Emit headers and partition #0
this.WriteWebpHeaders(stream, size0, vp8Size, riffSize, isVp8X, width, height, exifProfile, xmpProfile, iccProfile, hasAlpha, alphaData, alphaDataIsCompressed); this.WriteWebpHeaders(stream, size0, vp8Size, riffSize, isVp8X, width, height, exifProfile, xmpProfile, iccProfileBytes, hasAlpha, alphaData, alphaDataIsCompressed);
bitWriterPartZero.WriteToStream(stream); bitWriterPartZero.WriteToStream(stream);
// Write the encoded image to the stream. // Write the encoded image to the stream.
@ -679,7 +679,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
uint height, uint height,
ExifProfile exifProfile, ExifProfile exifProfile,
XmpProfile xmpProfile, XmpProfile xmpProfile,
IccProfile iccProfile, byte[] iccProfileBytes,
bool hasAlpha, bool hasAlpha,
Span<byte> alphaData, Span<byte> alphaData,
bool alphaDataIsCompressed) bool alphaDataIsCompressed)
@ -689,11 +689,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
// Write VP8X, header if necessary. // Write VP8X, header if necessary.
if (isVp8X) if (isVp8X)
{ {
this.WriteVp8XHeader(stream, exifProfile, xmpProfile, iccProfile, width, height, hasAlpha); this.WriteVp8XHeader(stream, exifProfile, xmpProfile, iccProfileBytes, width, height, hasAlpha);
if (iccProfile != null) if (iccProfileBytes != null)
{ {
this.WriteColorProfile(stream, iccProfile.ToByteArray()); this.WriteColorProfile(stream, iccProfileBytes);
} }
if (hasAlpha) if (hasAlpha)

10
src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs

@ -149,7 +149,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
if (exifProfile != null) if (exifProfile != null)
{ {
isVp8X = true; isVp8X = true;
riffSize += ExtendedFileChunkSize;
exifBytes = exifProfile.ToByteArray(); exifBytes = exifProfile.ToByteArray();
riffSize += this.MetadataChunkSize(exifBytes); riffSize += this.MetadataChunkSize(exifBytes);
} }
@ -157,7 +156,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
if (xmpProfile != null) if (xmpProfile != null)
{ {
isVp8X = true; isVp8X = true;
riffSize += ExtendedFileChunkSize;
xmpBytes = xmpProfile.Data; xmpBytes = xmpProfile.Data;
riffSize += this.MetadataChunkSize(xmpBytes); riffSize += this.MetadataChunkSize(xmpBytes);
} }
@ -165,11 +163,15 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
if (iccProfile != null) if (iccProfile != null)
{ {
isVp8X = true; isVp8X = true;
riffSize += ExtendedFileChunkSize;
iccBytes = iccProfile.ToByteArray(); iccBytes = iccProfile.ToByteArray();
riffSize += this.MetadataChunkSize(iccBytes); riffSize += this.MetadataChunkSize(iccBytes);
} }
if (isVp8X)
{
riffSize += ExtendedFileChunkSize;
}
this.Finish(); this.Finish();
uint size = (uint)this.NumBytes(); uint size = (uint)this.NumBytes();
size++; // One byte extra for the VP8L signature. size++; // One byte extra for the VP8L signature.
@ -182,7 +184,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter
// Write VP8X, header if necessary. // Write VP8X, header if necessary.
if (isVp8X) if (isVp8X)
{ {
this.WriteVp8XHeader(stream, exifProfile, xmpProfile, iccProfile, width, height, hasAlpha); this.WriteVp8XHeader(stream, exifProfile, xmpProfile, iccBytes, width, height, hasAlpha);
if (iccBytes != null) if (iccBytes != null)
{ {

31
tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs

@ -152,6 +152,37 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
Assert.Equal(expectedExif.Values.Count, actualExif.Values.Count); Assert.Equal(expectedExif.Values.Count, actualExif.Values.Count);
} }
[Theory]
[WithFile(TestImages.Webp.Lossy.WithIccp, PixelTypes.Rgba32, WebpFileFormatType.Lossless)]
[WithFile(TestImages.Webp.Lossy.WithIccp, PixelTypes.Rgba32, WebpFileFormatType.Lossy)]
public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider, WebpFileFormatType fileFormat)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> input = provider.GetImage(new WebpDecoder()))
{
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using (var memStream = new MemoryStream())
{
input.Save(memStream, new WebpEncoder()
{
FileFormat = fileFormat
});
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
{
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes);
}
}
}
}
[Theory] [Theory]
[WithFile(TestImages.Webp.Lossy.WithExifNotEnoughData, PixelTypes.Rgba32)] [WithFile(TestImages.Webp.Lossy.WithExifNotEnoughData, PixelTypes.Rgba32)]
public void WebpDecoder_IgnoresInvalidExifChunk<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_IgnoresInvalidExifChunk<TPixel>(TestImageProvider<TPixel> provider)

Loading…
Cancel
Save