📷 A modern, cross-platform, 2D Graphics library for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

180 lines
6.6 KiB

// <copyright file="TiffGenEntry.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ImageSharp.Formats;
/// <summary>
/// A utility data structure to represent Tiff IFD entries in unit tests.
/// </summary>
internal abstract class TiffGenEntry : ITiffGenDataSource
{
private TiffGenEntry(ushort tag, TiffType type, uint count)
{
this.Tag = tag;
this.Type = type;
this.Count = count;
}
public uint Count { get; }
public ushort Tag { get; }
public TiffType Type { get; }
public abstract IEnumerable<TiffGenDataBlock> GetData(bool isLittleEndian);
public static TiffGenEntry Ascii(ushort tag, string value)
{
return new TiffGenEntryAscii(tag, value);
}
public static TiffGenEntry Bytes(ushort tag, TiffType type, uint count, byte[] value)
{
return new TiffGenEntryBytes(tag, type, count, value);
}
public static TiffGenEntry Integer(ushort tag, TiffType type, int value)
{
return TiffGenEntry.Integer(tag, type, new int[] {value});
}
public static TiffGenEntry Integer(ushort tag, TiffType type, int[] value)
{
if (type != TiffType.Byte && type != TiffType.Short && type != TiffType.Long &&
type != TiffType.SByte && type != TiffType.SShort && type != TiffType.SLong)
throw new ArgumentException(nameof(type), "The specified type is not an integer type.");
return new TiffGenEntryInteger(tag, type, value);
}
public static TiffGenEntry Integer(ushort tag, TiffType type, uint value)
{
return TiffGenEntry.Integer(tag, type, new uint[] {value});
}
public static TiffGenEntry Integer(ushort tag, TiffType type, uint[] value)
{
if (type != TiffType.Byte && type != TiffType.Short && type != TiffType.Long &&
type != TiffType.SByte && type != TiffType.SShort && type != TiffType.SLong)
throw new ArgumentException(nameof(type), "The specified type is not an integer type.");
return new TiffGenEntryUnsignedInteger(tag, type, value);
}
private class TiffGenEntryAscii : TiffGenEntry
{
public TiffGenEntryAscii(ushort tag, string value) : base(tag, TiffType.Ascii, (uint)GetBytes(value).Length)
{
this.Value = value;
}
public string Value { get; }
public override IEnumerable<TiffGenDataBlock> GetData(bool isLittleEndian)
{
byte[] bytes = GetBytes(Value);
return new[] { new TiffGenDataBlock(bytes) };
}
private static byte[] GetBytes(string value)
{
return Encoding.ASCII.GetBytes($"{value}\0");
}
}
private class TiffGenEntryBytes : TiffGenEntry
{
public TiffGenEntryBytes(ushort tag, TiffType type, uint count, byte[] value) : base(tag, type, count)
{
this.Value = value;
}
public byte[] Value { get; }
public override IEnumerable<TiffGenDataBlock> GetData(bool isLittleEndian)
{
return new[] { new TiffGenDataBlock(Value) };
}
}
private class TiffGenEntryInteger : TiffGenEntry
{
public TiffGenEntryInteger(ushort tag, TiffType type, int[] value) : base(tag, type, (uint)value.Length)
{
this.Value = value;
}
public int[] Value { get; }
public override IEnumerable<TiffGenDataBlock> GetData(bool isLittleEndian)
{
byte[] bytes = GetBytes().SelectMany(b => b.WithByteOrder(isLittleEndian)).ToArray();
return new[] { new TiffGenDataBlock(bytes) };
}
private IEnumerable<byte[]> GetBytes()
{
switch (Type)
{
case TiffType.Byte:
return Value.Select(i => new byte[] { (byte)i });
case TiffType.Short:
return Value.Select(i => BitConverter.GetBytes((ushort)i));
case TiffType.Long:
return Value.Select(i => BitConverter.GetBytes((uint)i));
case TiffType.SByte:
return Value.Select(i => BitConverter.GetBytes((sbyte)i));
case TiffType.SShort:
return Value.Select(i => BitConverter.GetBytes((short)i));
case TiffType.SLong:
return Value.Select(i => BitConverter.GetBytes((int)i));
default:
throw new InvalidOperationException();
}
}
}
private class TiffGenEntryUnsignedInteger : TiffGenEntry
{
public TiffGenEntryUnsignedInteger(ushort tag, TiffType type, uint[] value) : base(tag, type, (uint)value.Length)
{
this.Value = value;
}
public uint[] Value { get; }
public override IEnumerable<TiffGenDataBlock> GetData(bool isLittleEndian)
{
byte[] bytes = GetBytes().SelectMany(b => b.WithByteOrder(isLittleEndian)).ToArray();
return new[] { new TiffGenDataBlock(bytes) };
}
private IEnumerable<byte[]> GetBytes()
{
switch (Type)
{
case TiffType.Byte:
return Value.Select(i => new byte[] { (byte)i });
case TiffType.Short:
return Value.Select(i => BitConverter.GetBytes((ushort)i));
case TiffType.Long:
return Value.Select(i => BitConverter.GetBytes((uint)i));
case TiffType.SByte:
return Value.Select(i => BitConverter.GetBytes((sbyte)i));
case TiffType.SShort:
return Value.Select(i => BitConverter.GetBytes((short)i));
case TiffType.SLong:
return Value.Select(i => BitConverter.GetBytes((int)i));
default:
throw new InvalidOperationException();
}
}
}
}
}