Browse Source

Add headers & aspect ratio helpers

pull/3153/head
winscripter 2 days ago
parent
commit
762edd1ec1
  1. 38
      src/ImageSharp/Formats/Jxl/JxlAspectRatioHelpers.cs
  2. 19
      src/ImageSharp/Formats/Jxl/Metadata/JxlAnimationHeader.cs
  3. 2
      src/ImageSharp/Formats/Jxl/Metadata/JxlImageMetadata.cs
  4. 68
      src/ImageSharp/Formats/Jxl/Metadata/JxlPreviewHeader.cs
  5. 73
      src/ImageSharp/Formats/Jxl/Metadata/JxlSizeHeader.cs

38
src/ImageSharp/Formats/Jxl/JxlAspectRatioHelpers.cs

@ -0,0 +1,38 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Jxl;
internal static class JxlAspectRatioHelpers
{
private static readonly SignedRational[] Ratios =
[
new(1, 1),
new(12, 10),
new(4, 3),
new(3, 2),
new(16, 9),
new(5, 4),
new(2, 1)
];
public static SignedRational FixedAspectRatios(int ratio) => Ratios[ratio - 1];
public static int FindAspectRatio(int x, int y)
{
for (int i = 0; i < 7; i++)
{
if (x == MultiplyTruncate(Ratios[i], y))
{
return i;
}
}
return 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int MultiplyTruncate(SignedRational rational, int multiplicand) => (multiplicand * rational.Numerator) / rational.Denominator;
}

19
src/ImageSharp/Formats/Jxl/Metadata/JxlAnimationHeader.cs

@ -0,0 +1,19 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Jxl.IO;
namespace SixLabors.ImageSharp.Formats.Jxl.Metadata;
internal sealed class JxlAnimationHeader : IJxlFields
{
public int TpsNumerator { get; set; }
public int TpsDenominator { get; set; }
public int LoopCount { get; set; }
public bool ContainsTimecodes { get; set; }
public bool Visit(JxlVisitor visitor) => throw new NotImplementedException();
}

2
src/ImageSharp/Formats/Jxl/Metadata/JxlImageMetadata.cs

@ -123,4 +123,6 @@ internal sealed class JxlImageMetadata : IJxlFields
this.Modular16BitBufferSufficient = bits <= 12;
}
public bool Visit(JxlVisitor visitor) => throw new NotImplementedException();
}

68
src/ImageSharp/Formats/Jxl/Metadata/JxlPreviewHeader.cs

@ -0,0 +1,68 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Jxl.IO;
namespace SixLabors.ImageSharp.Formats.Jxl.Metadata;
internal sealed class JxlPreviewHeader : IJxlFields
{
private bool div8;
private int ySizeDiv8;
private int ySize;
private int ratio;
private int xSizeDiv8;
private int xSize;
public int YSize => this.div8 ? (this.ySizeDiv8 * 8) : this.ySize;
public int XSize
{
get
{
if (this.ratio != 0)
{
SignedRational signedRational = JxlAspectRatioHelpers.FixedAspectRatios(this.ratio);
return JxlAspectRatioHelpers.MultiplyTruncate(signedRational, this.YSize);
}
return this.div8 ? (this.xSizeDiv8 * 8) : this.xSize;
}
}
public void Set(int x, int y)
{
if (x == 0 || y == 0)
{
throw new ArgumentException("Empty preview");
}
this.div8 = ((x % JxlFrameDimensions.BlockDimensions) | (y % JxlFrameDimensions.BlockDimensions)) == 0;
if (this.div8)
{
this.ySizeDiv8 = y / 8;
}
else
{
this.ySize = y;
}
this.ratio = JxlAspectRatioHelpers.FindAspectRatio(x, y);
if (this.ratio == 0)
{
if (this.div8)
{
this.xSizeDiv8 = x / 8;
}
else
{
this.xSize = x;
}
}
}
public bool Visit(JxlVisitor visitor) => throw new NotImplementedException();
}

73
src/ImageSharp/Formats/Jxl/Metadata/JxlSizeHeader.cs

@ -0,0 +1,73 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Jxl.IO;
namespace SixLabors.ImageSharp.Formats.Jxl.Metadata;
internal sealed class JxlSizeHeader : IJxlFields
{
private bool isSmall;
private int ySizeDiv8Minus1;
private int ySize;
private int ratio;
private int xSizeDiv8Minus1;
private int xSize;
public int YSize => this.isSmall ? ((this.ySizeDiv8Minus1 + 1) * 8) : this.ySize;
public int XSize
{
get
{
if (this.ratio != 0)
{
SignedRational aspectRatio = JxlAspectRatioHelpers.FixedAspectRatios(this.ratio);
return JxlAspectRatioHelpers.MultiplyTruncate(aspectRatio, this.YSize);
}
return this.isSmall ? ((this.xSizeDiv8Minus1 + 1) * 8) : this.xSize;
}
}
public void Set(int x, int y)
{
if (x > int.MaxValue || y > int.MaxValue)
{
throw new ArgumentException("Image too large");
}
if (x == 0 || y == 0)
{
throw new ArgumentException("Empty image");
}
this.ratio = JxlAspectRatioHelpers.FindAspectRatio(x, y);
this.isSmall = y < 256 && (y % JxlFrameDimensions.BlockDimensions) == 0
&& (this.ratio != 0 || (x <= 256 && (x % JxlFrameDimensions.BlockDimensions) == 0));
if (this.isSmall)
{
this.ySizeDiv8Minus1 = (y / 8) - 1;
}
else
{
this.ySize = y;
}
if (this.ratio == 0)
{
if (this.isSmall)
{
this.xSizeDiv8Minus1 = (x / 8) - 1;
}
else
{
this.xSize = x;
}
}
}
public bool Visit(JxlVisitor visitor) => throw new NotImplementedException();
}
Loading…
Cancel
Save