mirror of https://github.com/SixLabors/ImageSharp
4 changed files with 137 additions and 0 deletions
@ -0,0 +1,124 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers.Binary; |
|||
using System.Text; |
|||
using SixLabors.ImageSharp.Formats; |
|||
using SixLabors.ImageSharp.Formats.Png; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Png; |
|||
|
|||
public partial class PngDecoderTests |
|||
{ |
|||
[Fact] |
|||
public void Decode_IccLutExceedsVectorChannelCount_Throws() |
|||
{ |
|||
byte[] profileData = BuildLut16Profile(3, 15, 2, 2, 2); |
|||
byte[] pngData = BuildPng(profileData); |
|||
DecoderOptions options = new() { ColorProfileHandling = ColorProfileHandling.Convert }; |
|||
|
|||
Assert.Throws<InvalidIccProfileException>(() => Image.Load(options, pngData)); |
|||
} |
|||
|
|||
private static byte[] BuildLut16Profile(int inputChannels, int outputChannels, int clutPoints, int inputTableLength, int outputTableLength) |
|||
{ |
|||
using MemoryStream stream = new(); |
|||
|
|||
byte[] header = new byte[128]; |
|||
BinaryPrimitives.WriteUInt32BigEndian(header.AsSpan(8), 0x04300000U); |
|||
Encoding.ASCII.GetBytes("mntr").CopyTo(header, 12); |
|||
Encoding.ASCII.GetBytes("RGB ").CopyTo(header, 16); |
|||
Encoding.ASCII.GetBytes("XYZ ").CopyTo(header, 20); |
|||
stream.Write(header); |
|||
|
|||
WriteUInt32(1); |
|||
stream.Write(Encoding.ASCII.GetBytes("A2B0")); |
|||
long offsetPosition = stream.Position; |
|||
WriteUInt32(0); |
|||
long sizePosition = stream.Position; |
|||
WriteUInt32(0); |
|||
|
|||
long tagStart = stream.Position; |
|||
stream.Write(Encoding.ASCII.GetBytes("mft2")); |
|||
WriteUInt32(0); |
|||
stream.WriteByte((byte)inputChannels); |
|||
stream.WriteByte((byte)outputChannels); |
|||
stream.WriteByte((byte)clutPoints); |
|||
stream.WriteByte(0); |
|||
|
|||
for (int y = 0; y < 3; y++) |
|||
{ |
|||
for (int x = 0; x < 3; x++) |
|||
{ |
|||
WriteFix16(x == y ? 1D : 0D); |
|||
} |
|||
} |
|||
|
|||
WriteUInt16((ushort)inputTableLength); |
|||
WriteUInt16((ushort)outputTableLength); |
|||
|
|||
for (int channel = 0; channel < inputChannels; channel++) |
|||
{ |
|||
for (int i = 0; i < inputTableLength; i++) |
|||
{ |
|||
WriteUInt16((ushort)(i == 0 ? 0 : ushort.MaxValue)); |
|||
} |
|||
} |
|||
|
|||
int clutLength = (int)Math.Pow(clutPoints, inputChannels); |
|||
for (int i = 0; i < clutLength; i++) |
|||
{ |
|||
for (int channel = 0; channel < outputChannels; channel++) |
|||
{ |
|||
WriteUInt16(0x8000); |
|||
} |
|||
} |
|||
|
|||
for (int channel = 0; channel < outputChannels; channel++) |
|||
{ |
|||
for (int i = 0; i < outputTableLength; i++) |
|||
{ |
|||
WriteUInt16((ushort)(i == 0 ? 0 : ushort.MaxValue)); |
|||
} |
|||
} |
|||
|
|||
long tagEnd = stream.Position; |
|||
byte[] result = stream.ToArray(); |
|||
BinaryPrimitives.WriteUInt32BigEndian(result.AsSpan((int)offsetPosition), (uint)tagStart); |
|||
BinaryPrimitives.WriteUInt32BigEndian(result.AsSpan((int)sizePosition), (uint)(tagEnd - tagStart)); |
|||
BinaryPrimitives.WriteUInt32BigEndian(result, (uint)result.Length); |
|||
return result; |
|||
|
|||
void WriteUInt32(uint value) |
|||
{ |
|||
Span<byte> buffer = stackalloc byte[4]; |
|||
BinaryPrimitives.WriteUInt32BigEndian(buffer, value); |
|||
stream.Write(buffer); |
|||
} |
|||
|
|||
void WriteUInt16(ushort value) |
|||
{ |
|||
Span<byte> buffer = stackalloc byte[2]; |
|||
BinaryPrimitives.WriteUInt16BigEndian(buffer, value); |
|||
stream.Write(buffer); |
|||
} |
|||
|
|||
void WriteFix16(double value) |
|||
{ |
|||
int rawValue = (int)Math.Round(value * 65536D); |
|||
WriteUInt32(unchecked((uint)rawValue)); |
|||
} |
|||
} |
|||
|
|||
private static byte[] BuildPng(byte[] profileData) |
|||
{ |
|||
using Image<Rgb24> image = new(16, 16); |
|||
image.Metadata.IccProfile = new IccProfile(profileData); |
|||
|
|||
using MemoryStream stream = new(); |
|||
image.SaveAsPng(stream); |
|||
return stream.ToArray(); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue