mirror of https://github.com/SixLabors/ImageSharp
2 changed files with 95 additions and 40 deletions
@ -0,0 +1,93 @@ |
|||
using System; |
|||
using System.Buffers.Binary; |
|||
using SixLabors.ImageSharp.Common.Helpers; |
|||
using SixLabors.ImageSharp.MetaData; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Png |
|||
{ |
|||
/// <summary>
|
|||
/// The pHYs chunk specifies the intended pixel size or aspect ratio for display of the image.
|
|||
/// </summary>
|
|||
internal readonly struct PngPhysicalChunkData |
|||
{ |
|||
public const int Size = 9; |
|||
|
|||
public PngPhysicalChunkData(uint x, uint y, byte unitSpecifier) |
|||
{ |
|||
this.XAxisPixelsPerUnit = x; |
|||
this.YAxisPixelsPerUnit = y; |
|||
this.UnitSpecifier = unitSpecifier; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of pixels per unit on the X axis.
|
|||
/// </summary>
|
|||
public uint XAxisPixelsPerUnit { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of pixels per unit on the Y axis.
|
|||
/// </summary>
|
|||
public uint YAxisPixelsPerUnit { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the unit specifier.
|
|||
/// 0: unit is unknown
|
|||
/// 1: unit is the meter
|
|||
/// When the unit specifier is 0, the pHYs chunk defines pixel aspect ratio only; the actual size of the pixels remains unspecified.
|
|||
/// </summary>
|
|||
public byte UnitSpecifier { get; } |
|||
|
|||
/// <summary>
|
|||
/// Constructs the PngPhysicalChunkData from the provided metadata.
|
|||
/// If the resolution units are not in meters, they are automatically convereted.
|
|||
/// </summary>
|
|||
/// <param name="meta">The metadata.</param>
|
|||
/// <returns>The constructed PngPhysicalChunkData instance.</returns>
|
|||
public static PngPhysicalChunkData FromMetadata(ImageMetaData meta) |
|||
{ |
|||
byte unitSpecifier = 0; |
|||
uint x; |
|||
uint y; |
|||
|
|||
switch (meta.ResolutionUnits) |
|||
{ |
|||
case PixelResolutionUnit.AspectRatio: |
|||
unitSpecifier = 0; // Unspecified
|
|||
x = (uint)Math.Round(meta.HorizontalResolution); |
|||
y = (uint)Math.Round(meta.VerticalResolution); |
|||
break; |
|||
|
|||
case PixelResolutionUnit.PixelsPerInch: |
|||
unitSpecifier = 1; // Per meter
|
|||
x = (uint)Math.Round(UnitConverter.InchToMeter(meta.HorizontalResolution)); |
|||
y = (uint)Math.Round(UnitConverter.InchToMeter(meta.VerticalResolution)); |
|||
break; |
|||
|
|||
case PixelResolutionUnit.PixelsPerCentimeter: |
|||
unitSpecifier = 1; // Per meter
|
|||
x = (uint)Math.Round(UnitConverter.CmToMeter(meta.HorizontalResolution)); |
|||
y = (uint)Math.Round(UnitConverter.CmToMeter(meta.VerticalResolution)); |
|||
break; |
|||
|
|||
default: |
|||
unitSpecifier = 1; // Per meter
|
|||
x = (uint)Math.Round(meta.HorizontalResolution); |
|||
y = (uint)Math.Round(meta.VerticalResolution); |
|||
break; |
|||
} |
|||
|
|||
return new PngPhysicalChunkData(x, y, unitSpecifier); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Writes the data to the given buffer.
|
|||
/// </summary>
|
|||
/// <param name="buffer">The buffer.</param>
|
|||
public void WriteTo(Span<byte> buffer) |
|||
{ |
|||
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(0, 4), this.XAxisPixelsPerUnit); |
|||
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(4, 4), this.YAxisPixelsPerUnit); |
|||
buffer[8] = this.UnitSpecifier; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue