mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
46 changed files with 1582 additions and 198 deletions
@ -1,64 +1,78 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using SixLabors.ImageSharp.Formats.Tiff.Constants; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Exif; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff |
|||
{ |
|||
internal class EntryReader : BaseExifReader |
|||
{ |
|||
private readonly uint startOffset; |
|||
|
|||
private readonly SortedList<uint, Action> lazyLoaders; |
|||
|
|||
public EntryReader(Stream stream, ByteOrder byteOrder, uint ifdOffset, SortedList<uint, Action> lazyLoaders) |
|||
: base(stream) |
|||
{ |
|||
public EntryReader(Stream stream, ByteOrder byteOrder, MemoryAllocator allocator) |
|||
: base(stream, allocator) => |
|||
this.IsBigEndian = byteOrder == ByteOrder.BigEndian; |
|||
this.startOffset = ifdOffset; |
|||
this.lazyLoaders = lazyLoaders; |
|||
} |
|||
|
|||
public List<IExifValue> Values { get; } = new(); |
|||
|
|||
public uint NextIfdOffset { get; private set; } |
|||
public ulong NextIfdOffset { get; private set; } |
|||
|
|||
public void ReadTags() |
|||
public void ReadTags(bool isBigTiff, ulong ifdOffset) |
|||
{ |
|||
this.ReadValues(this.Values, this.startOffset); |
|||
this.NextIfdOffset = this.ReadUInt32(); |
|||
if (!isBigTiff) |
|||
{ |
|||
this.ReadValues(this.Values, (uint)ifdOffset); |
|||
this.NextIfdOffset = this.ReadUInt32(); |
|||
|
|||
this.ReadSubIfd(this.Values); |
|||
} |
|||
else |
|||
{ |
|||
this.ReadValues64(this.Values, ifdOffset); |
|||
this.NextIfdOffset = this.ReadUInt64(); |
|||
|
|||
this.ReadSubIfd(this.Values); |
|||
//// this.ReadSubIfd64(this.Values);
|
|||
} |
|||
} |
|||
|
|||
protected override void RegisterExtLoader(uint offset, Action reader) => |
|||
this.lazyLoaders.Add(offset, reader); |
|||
public void ReadBigValues() => this.ReadBigValues(this.Values); |
|||
} |
|||
|
|||
internal class HeaderReader : BaseExifReader |
|||
{ |
|||
public HeaderReader(Stream stream, ByteOrder byteOrder) |
|||
: base(stream) => |
|||
: base(stream, null) => |
|||
this.IsBigEndian = byteOrder == ByteOrder.BigEndian; |
|||
|
|||
public uint FirstIfdOffset { get; private set; } |
|||
public bool IsBigTiff { get; private set; } |
|||
|
|||
public uint ReadFileHeader() |
|||
public ulong FirstIfdOffset { get; private set; } |
|||
|
|||
public void ReadFileHeader() |
|||
{ |
|||
ushort magic = this.ReadUInt16(); |
|||
if (magic != TiffConstants.HeaderMagicNumber) |
|||
if (magic == TiffConstants.HeaderMagicNumber) |
|||
{ |
|||
TiffThrowHelper.ThrowInvalidHeader(); |
|||
this.IsBigTiff = false; |
|||
this.FirstIfdOffset = this.ReadUInt32(); |
|||
return; |
|||
} |
|||
else if (magic == TiffConstants.BigTiffHeaderMagicNumber) |
|||
{ |
|||
this.IsBigTiff = true; |
|||
|
|||
this.FirstIfdOffset = this.ReadUInt32(); |
|||
return this.FirstIfdOffset; |
|||
} |
|||
ushort bytesize = this.ReadUInt16(); |
|||
ushort reserve = this.ReadUInt16(); |
|||
if (bytesize == TiffConstants.BigTiffBytesize && reserve == 0) |
|||
{ |
|||
this.FirstIfdOffset = this.ReadUInt64(); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
protected override void RegisterExtLoader(uint offset, Action reader) => throw new NotSupportedException(); |
|||
TiffThrowHelper.ThrowInvalidHeader(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,21 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff |
|||
{ |
|||
/// <summary>
|
|||
/// The TIFF format type enum.
|
|||
/// </summary>
|
|||
public enum TiffFormatType |
|||
{ |
|||
/// <summary>
|
|||
/// The TIFF file format type.
|
|||
/// </summary>
|
|||
Default, |
|||
|
|||
/// <summary>
|
|||
/// The BigTIFF format type.
|
|||
/// </summary>
|
|||
BigTIFF |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Globalization; |
|||
|
|||
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif |
|||
{ |
|||
internal sealed class ExifLong8 : ExifValue<ulong> |
|||
{ |
|||
public ExifLong8(ExifTag<ulong> tag) |
|||
: base(tag) |
|||
{ |
|||
} |
|||
|
|||
public ExifLong8(ExifTagValue tag) |
|||
: base(tag) |
|||
{ |
|||
} |
|||
|
|||
private ExifLong8(ExifLong8 value) |
|||
: base(value) |
|||
{ |
|||
} |
|||
|
|||
public override ExifDataType DataType => ExifDataType.Long8; |
|||
|
|||
protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); |
|||
|
|||
public override bool TrySetValue(object value) |
|||
{ |
|||
if (base.TrySetValue(value)) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
switch (value) |
|||
{ |
|||
case int intValue: |
|||
if (intValue >= uint.MinValue) |
|||
{ |
|||
this.Value = (uint)intValue; |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
case uint uintValue: |
|||
this.Value = uintValue; |
|||
|
|||
return true; |
|||
case long intValue: |
|||
if (intValue >= 0) |
|||
{ |
|||
this.Value = (ulong)intValue; |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
default: |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public override IExifValue DeepClone() => new ExifLong8(this); |
|||
} |
|||
} |
|||
@ -0,0 +1,171 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif |
|||
{ |
|||
internal sealed class ExifLong8Array : ExifArrayValue<ulong> |
|||
{ |
|||
public ExifLong8Array(ExifTagValue tag) |
|||
: base(tag) |
|||
{ |
|||
} |
|||
|
|||
private ExifLong8Array(ExifLong8Array value) |
|||
: base(value) |
|||
{ |
|||
} |
|||
|
|||
public override ExifDataType DataType |
|||
{ |
|||
get |
|||
{ |
|||
if (this.Value is not null) |
|||
{ |
|||
foreach (ulong value in this.Value) |
|||
{ |
|||
if (value > uint.MaxValue) |
|||
{ |
|||
return ExifDataType.Long8; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return ExifDataType.Long; |
|||
} |
|||
} |
|||
|
|||
public override bool TrySetValue(object value) |
|||
{ |
|||
if (base.TrySetValue(value)) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
switch (value) |
|||
{ |
|||
case int val: |
|||
return this.SetSingle((ulong)Numerics.Clamp(val, 0, int.MaxValue)); |
|||
|
|||
case uint val: |
|||
return this.SetSingle((ulong)val); |
|||
|
|||
case short val: |
|||
return this.SetSingle((ulong)Numerics.Clamp(val, 0, short.MaxValue)); |
|||
|
|||
case ushort val: |
|||
return this.SetSingle((ulong)val); |
|||
|
|||
case long val: |
|||
return this.SetSingle((ulong)Numerics.Clamp(val, 0, long.MaxValue)); |
|||
|
|||
case long[] array: |
|||
{ |
|||
if (value.GetType() == typeof(ulong[])) |
|||
{ |
|||
return this.SetArray((ulong[])value); |
|||
} |
|||
|
|||
return this.SetArray(array); |
|||
} |
|||
|
|||
case int[] array: |
|||
{ |
|||
if (value.GetType() == typeof(uint[])) |
|||
{ |
|||
return this.SetArray((uint[])value); |
|||
} |
|||
|
|||
return this.SetArray(array); |
|||
} |
|||
|
|||
case short[] array: |
|||
{ |
|||
if (value.GetType() == typeof(ushort[])) |
|||
{ |
|||
return this.SetArray((ushort[])value); |
|||
} |
|||
|
|||
return this.SetArray(array); |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public override IExifValue DeepClone() => new ExifLong8Array(this); |
|||
|
|||
private bool SetSingle(ulong value) |
|||
{ |
|||
this.Value = new[] { value }; |
|||
return true; |
|||
} |
|||
|
|||
private bool SetArray(long[] values) |
|||
{ |
|||
var numbers = new ulong[values.Length]; |
|||
for (int i = 0; i < values.Length; i++) |
|||
{ |
|||
numbers[i] = (ulong)(values[i] < 0 ? 0 : values[i]); |
|||
} |
|||
|
|||
this.Value = numbers; |
|||
return true; |
|||
} |
|||
|
|||
private bool SetArray(ulong[] values) |
|||
{ |
|||
this.Value = values; |
|||
return true; |
|||
} |
|||
|
|||
private bool SetArray(int[] values) |
|||
{ |
|||
var numbers = new ulong[values.Length]; |
|||
for (int i = 0; i < values.Length; i++) |
|||
{ |
|||
numbers[i] = (ulong)Numerics.Clamp(values[i], 0, int.MaxValue); |
|||
} |
|||
|
|||
this.Value = numbers; |
|||
return true; |
|||
} |
|||
|
|||
private bool SetArray(uint[] values) |
|||
{ |
|||
var numbers = new ulong[values.Length]; |
|||
for (int i = 0; i < values.Length; i++) |
|||
{ |
|||
numbers[i] = (ulong)values[i]; |
|||
} |
|||
|
|||
this.Value = numbers; |
|||
return true; |
|||
} |
|||
|
|||
private bool SetArray(short[] values) |
|||
{ |
|||
var numbers = new ulong[values.Length]; |
|||
for (int i = 0; i < values.Length; i++) |
|||
{ |
|||
numbers[i] = (ulong)Numerics.Clamp(values[i], 0, short.MaxValue); |
|||
} |
|||
|
|||
this.Value = numbers; |
|||
return true; |
|||
} |
|||
|
|||
private bool SetArray(ushort[] values) |
|||
{ |
|||
var numbers = new ulong[values.Length]; |
|||
for (int i = 0; i < values.Length; i++) |
|||
{ |
|||
numbers[i] = (ulong)values[i]; |
|||
} |
|||
|
|||
this.Value = numbers; |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Globalization; |
|||
|
|||
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif |
|||
{ |
|||
internal sealed class ExifSignedLong8 : ExifValue<long> |
|||
{ |
|||
public ExifSignedLong8(ExifTagValue tag) |
|||
: base(tag) |
|||
{ |
|||
} |
|||
|
|||
private ExifSignedLong8(ExifSignedLong8 value) |
|||
: base(value) |
|||
{ |
|||
} |
|||
|
|||
public override ExifDataType DataType => ExifDataType.SignedLong8; |
|||
|
|||
protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); |
|||
|
|||
public override IExifValue DeepClone() => new ExifSignedLong8(this); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif |
|||
{ |
|||
internal sealed class ExifSignedLong8Array : ExifArrayValue<long> |
|||
{ |
|||
public ExifSignedLong8Array(ExifTagValue tag) |
|||
: base(tag) |
|||
{ |
|||
} |
|||
|
|||
private ExifSignedLong8Array(ExifSignedLong8Array value) |
|||
: base(value) |
|||
{ |
|||
} |
|||
|
|||
public override ExifDataType DataType => ExifDataType.SignedLong8; |
|||
|
|||
public override IExifValue DeepClone() => new ExifSignedLong8Array(this); |
|||
} |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
// ReSharper disable InconsistentNaming
|
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using SixLabors.ImageSharp.Formats.Tiff; |
|||
using SixLabors.ImageSharp.Metadata; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Exif; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|||
using Xunit; |
|||
using static SixLabors.ImageSharp.Tests.TestImages.BigTiff; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Tiff |
|||
{ |
|||
[Collection("RunSerial")] |
|||
[Trait("Format", "Tiff")] |
|||
public class BigTiffDecoderTests : TiffDecoderBaseTester |
|||
{ |
|||
[Theory] |
|||
[WithFile(BigTIFF, PixelTypes.Rgba32)] |
|||
[WithFile(BigTIFFLong, PixelTypes.Rgba32)] |
|||
[WithFile(BigTIFFLong8, PixelTypes.Rgba32)] |
|||
[WithFile(BigTIFFMotorola, PixelTypes.Rgba32)] |
|||
[WithFile(BigTIFFMotorolaLongStrips, PixelTypes.Rgba32)] |
|||
[WithFile(BigTIFFSubIFD4, PixelTypes.Rgba32)] |
|||
[WithFile(BigTIFFSubIFD8, PixelTypes.Rgba32)] |
|||
[WithFile(Indexed4_Deflate, PixelTypes.Rgba32)] |
|||
[WithFile(Indexed8_LZW, PixelTypes.Rgba32)] |
|||
[WithFile(MinIsBlack, PixelTypes.Rgba32)] |
|||
[WithFile(MinIsWhite, PixelTypes.Rgba32)] |
|||
public void TiffDecoder_CanDecode<TPixel>(TestImageProvider<TPixel> provider) |
|||
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider); |
|||
|
|||
[Theory] |
|||
[WithFile(BigTIFFLong8Tiles, PixelTypes.Rgba32)] |
|||
public void ThrowsNotSupported<TPixel>(TestImageProvider<TPixel> provider) |
|||
where TPixel : unmanaged, IPixel<TPixel> => Assert.Throws<NotSupportedException>(() => provider.GetImage(TiffDecoder)); |
|||
|
|||
[Theory] |
|||
[WithFile(Damaged_MinIsWhite_RLE, PixelTypes.Rgba32)] |
|||
[WithFile(Damaged_MinIsBlack_RLE, PixelTypes.Rgba32)] |
|||
public void DamagedFiles<TPixel>(TestImageProvider<TPixel> provider) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
Assert.Throws<ImageDifferenceIsOverThresholdException>(() => TestTiffDecoder(provider)); |
|||
|
|||
using Image<TPixel> image = provider.GetImage(TiffDecoder); |
|||
ExifProfile exif = image.Frames.RootFrame.Metadata.ExifProfile; |
|||
|
|||
// PhotometricInterpretation is required tag: https://www.awaresystems.be/imaging/tiff/tifftags/photometricinterpretation.html
|
|||
Assert.Null(exif.GetValueInternal(ExifTag.PhotometricInterpretation)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(BigTIFF, 24, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(BigTIFFLong, 24, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(BigTIFFLong8, 24, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(BigTIFFMotorola, 24, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(BigTIFFMotorolaLongStrips, 24, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(BigTIFFSubIFD4, 24, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(BigTIFFSubIFD8, 24, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(Indexed4_Deflate, 4, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(Indexed8_LZW, 8, 64, 64, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(MinIsWhite, 1, 32, 32, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
[InlineData(MinIsBlack, 1, 32, 32, 96, 96, PixelResolutionUnit.PixelsPerInch)] |
|||
public void Identify(string imagePath, int expectedPixelSize, int expectedWidth, int expectedHeight, double expectedHResolution, double expectedVResolution, PixelResolutionUnit expectedResolutionUnit) |
|||
{ |
|||
var testFile = TestFile.Create(imagePath); |
|||
using (var stream = new MemoryStream(testFile.Bytes, false)) |
|||
{ |
|||
IImageInfo info = Image.Identify(stream); |
|||
|
|||
Assert.Equal(expectedPixelSize, info.PixelType?.BitsPerPixel); |
|||
Assert.Equal(expectedWidth, info.Width); |
|||
Assert.Equal(expectedHeight, info.Height); |
|||
Assert.NotNull(info.Metadata); |
|||
Assert.Equal(expectedHResolution, info.Metadata.HorizontalResolution); |
|||
Assert.Equal(expectedVResolution, info.Metadata.VerticalResolution); |
|||
Assert.Equal(expectedResolutionUnit, info.Metadata.ResolutionUnits); |
|||
|
|||
TiffMetadata tiffmeta = info.Metadata.GetTiffMetadata(); |
|||
Assert.NotNull(tiffmeta); |
|||
Assert.Equal(TiffFormatType.BigTIFF, tiffmeta.FormatType); |
|||
} |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(BigTIFFLong, ImageSharp.ByteOrder.LittleEndian)] |
|||
[InlineData(BigTIFFMotorola, ImageSharp.ByteOrder.BigEndian)] |
|||
public void ByteOrder(string imagePath, ByteOrder expectedByteOrder) |
|||
{ |
|||
var testFile = TestFile.Create(imagePath); |
|||
using (var stream = new MemoryStream(testFile.Bytes, false)) |
|||
{ |
|||
IImageInfo info = Image.Identify(stream); |
|||
|
|||
Assert.NotNull(info.Metadata); |
|||
Assert.Equal(expectedByteOrder, info.Metadata.GetTiffMetadata().ByteOrder); |
|||
|
|||
stream.Seek(0, SeekOrigin.Begin); |
|||
|
|||
using var img = Image.Load(stream); |
|||
Assert.Equal(expectedByteOrder, img.Metadata.GetTiffMetadata().ByteOrder); |
|||
} |
|||
} |
|||
|
|||
[Theory] |
|||
[WithFile(BigTIFFSubIFD8, PixelTypes.Rgba32)] |
|||
public void TiffDecoder_SubIfd8<TPixel>(TestImageProvider<TPixel> provider) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
using Image<TPixel> image = provider.GetImage(TiffDecoder); |
|||
|
|||
ExifProfile meta = image.Frames.RootFrame.Metadata.ExifProfile; |
|||
|
|||
Assert.Equal(0, meta.InvalidTags.Count); |
|||
Assert.Equal(6, meta.Values.Count); |
|||
Assert.Equal(64, (int)meta.GetValue(ExifTag.ImageWidth).Value); |
|||
Assert.Equal(64, (int)meta.GetValue(ExifTag.ImageLength).Value); |
|||
Assert.Equal(64, (int)meta.GetValue(ExifTag.RowsPerStrip).Value); |
|||
|
|||
Assert.Equal(1, meta.Values.Count(v => (ushort)v.Tag == (ushort)ExifTagValue.ImageWidth)); |
|||
Assert.Equal(1, meta.Values.Count(v => (ushort)v.Tag == (ushort)ExifTagValue.StripOffsets)); |
|||
Assert.Equal(1, meta.Values.Count(v => (ushort)v.Tag == (ushort)ExifTagValue.StripByteCounts)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,260 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers.Binary; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using SixLabors.ImageSharp.Formats.Tiff; |
|||
using SixLabors.ImageSharp.Formats.Tiff.Writers; |
|||
using SixLabors.ImageSharp.Metadata; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Exif; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Tiff |
|||
{ |
|||
[Trait("Format", "Tiff")] |
|||
public class BigTiffMetadataTests |
|||
{ |
|||
[Fact] |
|||
public void ExifLong8() |
|||
{ |
|||
var long8 = new ExifLong8(ExifTagValue.StripByteCounts); |
|||
|
|||
Assert.True(long8.TrySetValue(0)); |
|||
Assert.Equal(0UL, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(100u)); |
|||
Assert.Equal(100UL, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(ulong.MaxValue)); |
|||
Assert.Equal(ulong.MaxValue, long8.GetValue()); |
|||
|
|||
Assert.False(long8.TrySetValue(-65)); |
|||
Assert.Equal(ulong.MaxValue, long8.GetValue()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ExifSignedLong8() |
|||
{ |
|||
var long8 = new ExifSignedLong8(ExifTagValue.ImageID); |
|||
|
|||
Assert.False(long8.TrySetValue(0)); |
|||
|
|||
Assert.True(long8.TrySetValue(0L)); |
|||
Assert.Equal(0L, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(-100L)); |
|||
Assert.Equal(-100L, long8.GetValue()); |
|||
Assert.Equal(ExifDataType.SignedLong8, long8.DataType); |
|||
|
|||
Assert.True(long8.TrySetValue(long.MaxValue)); |
|||
Assert.Equal(long.MaxValue, long8.GetValue()); |
|||
Assert.Equal(ExifDataType.SignedLong8, long8.DataType); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ExifLong8Array() |
|||
{ |
|||
var long8 = new ExifLong8Array(ExifTagValue.StripOffsets); |
|||
|
|||
Assert.True(long8.TrySetValue((short)-123)); |
|||
Assert.Equal(new[] { 0UL }, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue((ushort)123)); |
|||
Assert.Equal(new[] { 123UL }, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue((short)123)); |
|||
Assert.Equal(new[] { 123UL }, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(123)); |
|||
Assert.Equal(new[] { 123UL }, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(123u)); |
|||
Assert.Equal(new[] { 123UL }, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(123L)); |
|||
Assert.Equal(new[] { 123UL }, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(123UL)); |
|||
Assert.Equal(new[] { 123UL }, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(new short[] { -1, 2, -3, 4 })); |
|||
Assert.Equal(new ulong[] { 0, 2UL, 0, 4UL }, long8.GetValue()); |
|||
|
|||
Assert.True(long8.TrySetValue(new[] { 1, 2, 3, 4 })); |
|||
Assert.Equal(new[] { 1UL, 2UL, 3UL, 4UL }, long8.GetValue()); |
|||
Assert.Equal(ExifDataType.Long, long8.DataType); |
|||
|
|||
Assert.True(long8.TrySetValue(new[] { 1, 2, 3, 4, long.MaxValue })); |
|||
Assert.Equal(new[] { 1UL, 2UL, 3UL, 4UL, (ulong)long.MaxValue }, long8.GetValue()); |
|||
Assert.Equal(ExifDataType.Long8, long8.DataType); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ExifSignedLong8Array() |
|||
{ |
|||
var long8 = new ExifSignedLong8Array(ExifTagValue.StripOffsets); |
|||
|
|||
Assert.True(long8.TrySetValue(new[] { 0L })); |
|||
Assert.Equal(new[] { 0L }, long8.GetValue()); |
|||
Assert.Equal(ExifDataType.SignedLong8, long8.DataType); |
|||
|
|||
Assert.True(long8.TrySetValue(new[] { -1L, 2L, long.MinValue, 4L })); |
|||
Assert.Equal(new[] { -1L, 2L, long.MinValue, 4L }, long8.GetValue()); |
|||
Assert.Equal(ExifDataType.SignedLong8, long8.DataType); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NotCoveredTags() |
|||
{ |
|||
using var input = new Image<Rgba32>(10, 10); |
|||
|
|||
var testTags = new Dictionary<ExifTag, (ExifDataType DataType, object Value)> |
|||
{ |
|||
{ new ExifTag<float[]>((ExifTagValue)0xdd01), (ExifDataType.SingleFloat, new float[] { 1.2f, 2.3f, 4.5f }) }, |
|||
{ new ExifTag<float>((ExifTagValue)0xdd02), (ExifDataType.SingleFloat, 2.345f) }, |
|||
{ new ExifTag<double[]>((ExifTagValue)0xdd03), (ExifDataType.DoubleFloat, new double[] { 4.5, 6.7 }) }, |
|||
{ new ExifTag<double>((ExifTagValue)0xdd04), (ExifDataType.DoubleFloat, 8.903) }, |
|||
{ new ExifTag<sbyte>((ExifTagValue)0xdd05), (ExifDataType.SignedByte, (sbyte)-3) }, |
|||
{ new ExifTag<sbyte[]>((ExifTagValue)0xdd06), (ExifDataType.SignedByte, new sbyte[] { -3, 0, 5 }) }, |
|||
{ new ExifTag<int[]>((ExifTagValue)0xdd07), (ExifDataType.SignedLong, new int[] { int.MinValue, 1, int.MaxValue }) }, |
|||
{ new ExifTag<uint[]>((ExifTagValue)0xdd08), (ExifDataType.Long, new uint[] { 0, 1, uint.MaxValue }) }, |
|||
{ new ExifTag<short>((ExifTagValue)0xdd09), (ExifDataType.SignedShort, (short)-1234) }, |
|||
{ new ExifTag<ushort>((ExifTagValue)0xdd10), (ExifDataType.Short, (ushort)1234) }, |
|||
}; |
|||
|
|||
// arrange
|
|||
var values = new List<IExifValue>(); |
|||
foreach (KeyValuePair<ExifTag, (ExifDataType DataType, object Value)> tag in testTags) |
|||
{ |
|||
ExifValue newExifValue = ExifValues.Create((ExifTagValue)(ushort)tag.Key, tag.Value.DataType, tag.Value.Value is Array); |
|||
|
|||
Assert.True(newExifValue.TrySetValue(tag.Value.Value)); |
|||
values.Add(newExifValue); |
|||
} |
|||
|
|||
input.Frames.RootFrame.Metadata.ExifProfile = new ExifProfile(values, Array.Empty<ExifTag>()); |
|||
|
|||
// act
|
|||
var encoder = new TiffEncoder(); |
|||
using var memStream = new MemoryStream(); |
|||
input.Save(memStream, encoder); |
|||
|
|||
// assert
|
|||
memStream.Position = 0; |
|||
using var output = Image.Load<Rgba32>(memStream); |
|||
ImageFrameMetadata loadedFrameMetadata = output.Frames.RootFrame.Metadata; |
|||
foreach (KeyValuePair<ExifTag, (ExifDataType DataType, object Value)> tag in testTags) |
|||
{ |
|||
IExifValue exifValue = loadedFrameMetadata.ExifProfile.GetValueInternal(tag.Key); |
|||
Assert.NotNull(exifValue); |
|||
object value = exifValue.GetValue(); |
|||
|
|||
Assert.Equal(tag.Value.DataType, exifValue.DataType); |
|||
{ |
|||
Assert.Equal(value, tag.Value.Value); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void NotCoveredTags64bit() |
|||
{ |
|||
var testTags = new Dictionary<ExifTag, (ExifDataType DataType, object Value)> |
|||
{ |
|||
{ new ExifTag<ulong>((ExifTagValue)0xdd11), (ExifDataType.Long8, ulong.MaxValue) }, |
|||
{ new ExifTag<long>((ExifTagValue)0xdd12), (ExifDataType.SignedLong8, long.MaxValue) }, |
|||
//// WriteIfdTags64Bit: arrays aren't support (by our code)
|
|||
////{ new ExifTag<ulong[]>((ExifTagValue)0xdd13), (ExifDataType.Long8, new ulong[] { 0, 1234, 56789UL, ulong.MaxValue }) },
|
|||
////{ new ExifTag<long[]>((ExifTagValue)0xdd14), (ExifDataType.SignedLong8, new long[] { -1234, 56789L, long.MaxValue }) },
|
|||
}; |
|||
|
|||
var values = new List<IExifValue>(); |
|||
foreach (KeyValuePair<ExifTag, (ExifDataType DataType, object Value)> tag in testTags) |
|||
{ |
|||
ExifValue newExifValue = ExifValues.Create((ExifTagValue)(ushort)tag.Key, tag.Value.DataType, tag.Value.Value is Array); |
|||
|
|||
Assert.True(newExifValue.TrySetValue(tag.Value.Value)); |
|||
values.Add(newExifValue); |
|||
} |
|||
|
|||
// act
|
|||
byte[] inputBytes = WriteIfdTags64Bit(values); |
|||
Configuration config = Configuration.Default; |
|||
var reader = new EntryReader( |
|||
new MemoryStream(inputBytes), |
|||
BitConverter.IsLittleEndian ? ByteOrder.LittleEndian : ByteOrder.BigEndian, |
|||
config.MemoryAllocator); |
|||
|
|||
reader.ReadTags(true, 0); |
|||
|
|||
List<IExifValue> outputTags = reader.Values; |
|||
|
|||
// assert
|
|||
foreach (KeyValuePair<ExifTag, (ExifDataType DataType, object Value)> tag in testTags) |
|||
{ |
|||
IExifValue exifValue = outputTags.Find(t => t.Tag == tag.Key); |
|||
Assert.NotNull(exifValue); |
|||
object value = exifValue.GetValue(); |
|||
|
|||
Assert.Equal(tag.Value.DataType, exifValue.DataType); |
|||
{ |
|||
Assert.Equal(value, tag.Value.Value); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static byte[] WriteIfdTags64Bit(List<IExifValue> values) |
|||
{ |
|||
byte[] buffer = new byte[8]; |
|||
var ms = new MemoryStream(); |
|||
var writer = new TiffStreamWriter(ms); |
|||
WriteLong8(writer, buffer, (ulong)values.Count); |
|||
|
|||
foreach (IExifValue entry in values) |
|||
{ |
|||
writer.Write((ushort)entry.Tag); |
|||
writer.Write((ushort)entry.DataType); |
|||
WriteLong8(writer, buffer, ExifWriter.GetNumberOfComponents(entry)); |
|||
|
|||
uint length = ExifWriter.GetLength(entry); |
|||
|
|||
Assert.True(length <= 8); |
|||
|
|||
if (length <= 8) |
|||
{ |
|||
int sz = ExifWriter.WriteValue(entry, buffer, 0); |
|||
DebugGuard.IsTrue(sz == length, "Incorrect number of bytes written"); |
|||
|
|||
// write padded
|
|||
writer.BaseStream.Write(buffer.AsSpan(0, sz)); |
|||
int d = sz % 8; |
|||
if (d != 0) |
|||
{ |
|||
writer.BaseStream.Write(new byte[d]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
WriteLong8(writer, buffer, 0); |
|||
|
|||
return ms.ToArray(); |
|||
} |
|||
|
|||
private static void WriteLong8(TiffStreamWriter writer, byte[] buffer, ulong value) |
|||
{ |
|||
if (writer.IsLittleEndian) |
|||
{ |
|||
BinaryPrimitives.WriteUInt64LittleEndian(buffer, value); |
|||
} |
|||
else |
|||
{ |
|||
BinaryPrimitives.WriteUInt64BigEndian(buffer, value); |
|||
} |
|||
|
|||
writer.BaseStream.Write(buffer); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
// ReSharper disable InconsistentNaming
|
|||
using SixLabors.ImageSharp.Formats; |
|||
using SixLabors.ImageSharp.Formats.Tiff; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
|||
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Tiff |
|||
{ |
|||
public abstract class TiffDecoderBaseTester |
|||
{ |
|||
protected static TiffDecoder TiffDecoder => new TiffDecoder(); |
|||
|
|||
protected static MagickReferenceDecoder ReferenceDecoder => new MagickReferenceDecoder(); |
|||
|
|||
protected static void TestTiffDecoder<TPixel>(TestImageProvider<TPixel> provider, IImageDecoder referenceDecoder = null, bool useExactComparer = true, float compareTolerance = 0.001f) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
using Image<TPixel> image = provider.GetImage(TiffDecoder); |
|||
image.DebugSave(provider); |
|||
image.CompareToOriginal( |
|||
provider, |
|||
useExactComparer ? ImageComparer.Exact : ImageComparer.Tolerant(compareTolerance), |
|||
referenceDecoder ?? ReferenceDecoder); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:ddb202145a9bce7670cc372ee578de5a53cd52cc8d5ae8a9ebdc9f9c4f4a7e81 |
|||
size 12480 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:90178643a159ec50335e9314836df924233debeb100763af0f77cd1be3cf58ab |
|||
size 12480 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:b38e61ccb01e10e26fb10c335fc6fca9ad087b0fb0df833e54bb02d1246e20d5 |
|||
size 12480 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:a2d92b0c430cefc390f13961e00950ee7246b013335594dd249ba823eb3c3fdb |
|||
size 12564 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:ace8a27dbed9f918993615e545a12310b84ad94bc6af8e256258e69731f1c7ce |
|||
size 12480 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:2c5ebdc3774955d3b47644f57bd023e764a93ca2271118152ae920b34c1784bb |
|||
size 12480 |
|||
@ -0,0 +1,220 @@ |
|||
These images were created by [AWare Systems](http://www.awaresystems.be/). |
|||
|
|||
# Index |
|||
|
|||
[Classic.tif](#classictif) |
|||
[BigTIFF.tif](#bigtifftif) |
|||
[BigTIFFMotorola.tif](#bigtiffmotorolatif) |
|||
[BigTIFFLong.tif](#bigtifflongtif) |
|||
[BigTIFFLong8.tif](#bigtifflong8tif) |
|||
[BigTIFFMotorolaLongStrips.tif](#bigtiffmotorolalongstripstif) |
|||
[BigTIFFLong8Tiles.tif](#bigtifflong8tilestif) |
|||
[BigTIFFSubIFD4.tif](#bigtiffsubifd4tif) |
|||
[BigTIFFSubIFD8.tif](#bigtiffsubifd8tif) |
|||
|
|||
# Classic.tif |
|||
|
|||
Classic.tif is a basic Classic TIFF file. All files in this package have the same actual image content, so this TIFF file serves as a reference. |
|||
|
|||
Format: Classic TIFF |
|||
Byte Order: Intel |
|||
Ifd Offset: 12302 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 8 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Short): 12288 |
|||
|
|||
# BigTIFF.tif |
|||
|
|||
BigTIFF.tif ressembles Classic.tif as close as possible. Except that it's a BigTIFF, that is... |
|||
|
|||
Format: BigTIFF |
|||
Byte Order: Intel |
|||
Ifd Offset: 12304 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 16 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Short): 12288 |
|||
|
|||
# BigTIFFMotorola.tif |
|||
|
|||
BigTIFFMotorola.tif reverses the byte order. |
|||
|
|||
Format: BigTIFF |
|||
Byte Order: Motorola |
|||
Ifd Offset: 12304 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 16 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Short): 12288 |
|||
|
|||
# BigTIFFLong.tif |
|||
|
|||
All previous TIFFs specify DataType Short for StripOffsets and StripByteCounts tags. This BigTIFF instead specifies DataType Long, for these tags. |
|||
|
|||
Format: BigTIFF |
|||
Byte Order: Intel |
|||
Ifd Offset: 12304 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Long): 16 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Long): 12288 |
|||
|
|||
# BigTIFFLong8.tif |
|||
|
|||
This next one specifies DataType Long8, for StripOffsets and StripByteCounts tags. |
|||
|
|||
Format: BigTIFF |
|||
Byte Order: Intel |
|||
Ifd Offset: 12304 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Long8): 16 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Long8): 12288 |
|||
|
|||
# BigTIFFMotorolaLongStrips.tif |
|||
|
|||
This BigTIFF has Motorola byte order, plus, it's divided over two strips. StripOffsets and StripByteCounts tags have DataType Long, so their actual value fits inside the IFD. |
|||
|
|||
Format: BigTIFF |
|||
Byte Order: Motorola |
|||
Ifd Offset: 12304 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (2 Long): 16, 6160 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 32 |
|||
StripByteCounts (2 Long): 6144, 6144 |
|||
|
|||
# BigTIFFLong8Tiles.tif |
|||
|
|||
BigTIFFLong8Tiles.tif is a tiled BigTIFF. TileOffsets and TileByteCounts tags specify DataType Long8. |
|||
|
|||
Format: BigTIFF |
|||
Byte Order: Intel |
|||
Ifd Offset: 12368 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
SamplesPerPixel (1 Short): 3 |
|||
TileWidth (1 Short): 32 |
|||
TileLength (1 Short): 32 |
|||
TileOffsets (4 Long8): 16, 3088, 6160, 9232 |
|||
TileByteCounts (4 Long8): 3072, 3072, 3072, 3072 |
|||
|
|||
# BigTIFFSubIFD4.tif |
|||
|
|||
This BigTIFF contains two pages, the second page showing almost the same image content as the first, except that the black square is white, and text color is black. Both pages point to a downsample SubIFD, using SubIFDs DataType TIFF_IFD. |
|||
|
|||
Format: BigTIFF |
|||
Byte Order: Intel |
|||
Ifd Offset: 15572 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 3284 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Short): 12288 |
|||
SubIFDs (1 IFD): 3088 |
|||
SubIfd Offset: 3088 |
|||
NewSubFileType (1 Long): 1 |
|||
ImageWidth (1 Short): 32 |
|||
ImageLength (1 Short): 32 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 16 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 32 |
|||
StripByteCounts (1 Short): 3072 |
|||
Ifd Offset: 31324 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 19036 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Short): 12288 |
|||
SubIFDs (1 IFD): 18840 |
|||
SubIfd Offset: 18840 |
|||
NewSubFileType (1 Long): 1 |
|||
ImageWidth (1 Short): 32 |
|||
ImageLength (1 Short): 32 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 15768 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 32 |
|||
StripByteCounts (1 Short): 3072 |
|||
|
|||
# BigTIFFSubIFD8.tif |
|||
|
|||
BigTIFFSubIFD4.tif is very much the same as BigTIFFSubIFD4.tif, except that the new DataType TIFF_IFD8 is used for the SubIFDs tag. |
|||
|
|||
Format: BigTIFF |
|||
Byte Order: Intel |
|||
Ifd Offset: 15572 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 3284 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Short): 12288 |
|||
SubIFDs (1 IFD8): 3088 |
|||
SubIfd Offset: 3088 |
|||
NewSubFileType (1 Long): 1 |
|||
ImageWidth (1 Short): 32 |
|||
ImageLength (1 Short): 32 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 16 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 32 |
|||
StripByteCounts (1 Short): 3072 |
|||
Ifd Offset: 31324 |
|||
ImageWidth (1 Short): 64 |
|||
ImageLength (1 Short): 64 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 19036 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 64 |
|||
StripByteCounts (1 Short): 12288 |
|||
SubIFDs (1 IFD8): 18840 |
|||
SubIfd Offset: 18840 |
|||
NewSubFileType (1 Long): 1 |
|||
ImageWidth (1 Short): 32 |
|||
ImageLength (1 Short): 32 |
|||
BitsPerSample (3 Short): 8, 8, 8 |
|||
PhotometricInterpretation (1 Short): RGB |
|||
StripOffsets (1 Short): 15768 |
|||
SamplesPerPixel (1 Short): 3 |
|||
RowsPerStrip (1 Short): 32 |
|||
StripByteCounts (1 Short): 3072 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:85c8da46abc2284f0ddac10bd03a7c98ee51024840b7e43f41f1c6a09bc02e7e |
|||
size 31520 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:93e5ac30f507bec7936746ad6e109631c09f9b2332081e986063219ad2452a4a |
|||
size 31520 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:38ba3717b284d7914243609576d0f9b75d732692bf05e2e1ec8b119feb1409fd |
|||
size 687 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:ca404b3ec5560b82169855f0ae69e64c6bc7286117b95fc0e0d505e5e356fa0e |
|||
size 2548 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:ac0471c1600f6e5fb47037dab07172aff524abc866a40c9ec54279bd49cbef77 |
|||
size 517 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:038a298bcace02810054af650f490b6858863c8755e41b786605aa807b43350a |
|||
size 509 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:a95b0b46bf4f75babb86d9ec74694e6d684087504be214df48a6c8a54338834c |
|||
size 517 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:038a298bcace02810054af650f490b6858863c8755e41b786605aa807b43350a |
|||
size 509 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:cfa7fcf6927be5de644beb238067479e8d834d0cbe2257b00302f5dde84a1c1a |
|||
size 12404 |
|||
@ -0,0 +1,5 @@ |
|||
#### BigTIFF samples. |
|||
|
|||
For details: [BigTIFFSamples.md](BigTIFFSamples.md) |
|||
|
|||
Downloaded from https://www.awaresystems.be/imaging/tiff/bigtiff.html |
|||
Loading…
Reference in new issue