Browse Source

A little cleanup

pull/1570/head
Brian Popow 5 years ago
parent
commit
cab2e05cc4
  1. 32
      src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs
  2. 10
      src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs
  3. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero1TiffColor.cs
  4. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero4TiffColor.cs
  5. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero8TiffColor.cs
  6. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs
  7. 14
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
  8. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero1TiffColor.cs
  9. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero4TiffColor.cs
  10. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor.cs
  11. 5
      src/ImageSharp/Formats/Tiff/README.md
  12. 6
      src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs
  13. 6
      src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
  14. 20
      src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
  15. 6
      src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
  16. 54
      src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs
  17. 40
      src/ImageSharp/Formats/Tiff/TiffFrameMetadataResolutionExtensions.cs
  18. 33
      src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs
  19. 19
      src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs

32
src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs

@ -15,42 +15,32 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
/// </summary>
internal abstract class TiffBaseCompression
{
private readonly MemoryAllocator allocator;
private readonly TiffPhotometricInterpretation photometricInterpretation;
private readonly int width;
private readonly int bitsPerPixel;
private readonly TiffPredictor predictor;
protected TiffBaseCompression(MemoryAllocator allocator) => this.allocator = allocator;
protected TiffBaseCompression(MemoryAllocator allocator) => this.Allocator = allocator;
protected TiffBaseCompression(MemoryAllocator allocator, TiffPhotometricInterpretation photometricInterpretation, int width)
: this(allocator)
{
this.photometricInterpretation = photometricInterpretation;
this.width = width;
this.PhotometricInterpretation = photometricInterpretation;
this.Width = width;
}
protected TiffBaseCompression(MemoryAllocator allocator, int width, int bitsPerPixel, TiffPredictor predictor)
: this(allocator)
{
this.width = width;
this.bitsPerPixel = bitsPerPixel;
this.predictor = predictor;
this.Width = width;
this.BitsPerPixel = bitsPerPixel;
this.Predictor = predictor;
}
protected MemoryAllocator Allocator => this.allocator;
protected MemoryAllocator Allocator { get; }
protected TiffPhotometricInterpretation PhotometricInterpretation => this.photometricInterpretation;
protected TiffPhotometricInterpretation PhotometricInterpretation { get; }
protected int Width => this.width;
protected int Width { get; }
protected int BitsPerPixel => this.bitsPerPixel;
protected int BitsPerPixel { get; }
protected TiffPredictor Predictor => this.predictor;
protected TiffPredictor Predictor { get; }
/// <summary>
/// Decompresses image data into the supplied buffer.

10
src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs

@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
return ByteOrder.BigEndian;
}
throw TiffThrowHelper.InvalidHeader();
throw TiffThrowHelper.ThrowInvalidHeader();
}
private IEnumerable<ExifProfile> ReadIfds()
@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
readers.Add(reader);
}
// sequential reading big values
// Sequential reading big values.
foreach (Action loader in this.lazyLoaders.Values)
{
loader();
@ -78,7 +78,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
return list;
}
/// <summary><see cref="DuplicateKeyComparer{TKey}"/> used for possiblity add a duplicate offsets (but tags don't duplicate).</summary>
/// <summary>
/// <see cref="DuplicateKeyComparer{TKey}"/> used for possibility add a duplicate offsets (but tags don't duplicate).
/// </summary>
/// <typeparam name="TKey">The type of the key.</typeparam>
private class DuplicateKeyComparer<TKey> : IComparer<TKey>
where TKey : IComparable
@ -87,7 +89,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
int result = x.CompareTo(y);
// Handle equality as beeing greater
// Handle equality as being greater.
return (result == 0) ? 1 : result;
}
}

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero1TiffColor.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
/// <summary>
/// Implements the 'BlackIsZero' photometric interpretation (optimised for bilevel images).
/// Implements the 'BlackIsZero' photometric interpretation (optimized for bilevel images).
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal class BlackIsZero1TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero4TiffColor.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
/// <summary>
/// Implements the 'BlackIsZero' photometric interpretation (optimised for 4-bit grayscale images).
/// Implements the 'BlackIsZero' photometric interpretation (optimized for 4-bit grayscale images).
/// </summary>
internal class BlackIsZero4TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero8TiffColor.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
/// <summary>
/// Implements the 'BlackIsZero' photometric interpretation (optimised for 8-bit grayscale images).
/// Implements the 'BlackIsZero' photometric interpretation (optimized for 8-bit grayscale images).
/// </summary>
internal class BlackIsZero8TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
/// <summary>
/// Implements the 'RGB' photometric interpretation (optimised for 8-bit full color images).
/// Implements the 'RGB' photometric interpretation (optimized for 8-bit full color images).
/// </summary>
internal class Rgb888TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>

14
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs

@ -14,17 +14,17 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
BlackIsZero,
/// <summary>
/// Grayscale: 0 is imaged as black. The maximum value is imaged as white. Optimised implementation for bilevel images.
/// Grayscale: 0 is imaged as black. The maximum value is imaged as white. Optimized implementation for bilevel images.
/// </summary>
BlackIsZero1,
/// <summary>
/// Grayscale: 0 is imaged as black. The maximum value is imaged as white. Optimised implementation for 4-bit images.
/// Grayscale: 0 is imaged as black. The maximum value is imaged as white. Optimized implementation for 4-bit images.
/// </summary>
BlackIsZero4,
/// <summary>
/// Grayscale: 0 is imaged as black. The maximum value is imaged as white. Optimised implementation for 8-bit images.
/// Grayscale: 0 is imaged as black. The maximum value is imaged as white. Optimized implementation for 8-bit images.
/// </summary>
BlackIsZero8,
@ -34,17 +34,17 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
WhiteIsZero,
/// <summary>
/// Grayscale: 0 is imaged as white. The maximum value is imaged as black. Optimised implementation for bilevel images.
/// Grayscale: 0 is imaged as white. The maximum value is imaged as black. Optimized implementation for bilevel images.
/// </summary>
WhiteIsZero1,
/// <summary>
/// Grayscale: 0 is imaged as white. The maximum value is imaged as black. Optimised implementation for 4-bit images.
/// Grayscale: 0 is imaged as white. The maximum value is imaged as black. Optimized implementation for 4-bit images.
/// </summary>
WhiteIsZero4,
/// <summary>
/// Grayscale: 0 is imaged as white. The maximum value is imaged as black. Optimised implementation for 8-bit images.
/// Grayscale: 0 is imaged as white. The maximum value is imaged as black. Optimized implementation for 8-bit images.
/// </summary>
WhiteIsZero8,
@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
Rgb,
/// <summary>
/// RGB Full Color. Optimised implementation for 8-bit images.
/// RGB Full Color. Optimized implementation for 8-bit images.
/// </summary>
Rgb888,

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero1TiffColor.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
/// <summary>
/// Implements the 'WhiteIsZero' photometric interpretation (optimised for bilevel images).
/// Implements the 'WhiteIsZero' photometric interpretation (optimized for bilevel images).
/// </summary>
internal class WhiteIsZero1TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero4TiffColor.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
/// <summary>
/// Implements the 'WhiteIsZero' photometric interpretation (optimised for 4-bit grayscale images).
/// Implements the 'WhiteIsZero' photometric interpretation (optimized for 4-bit grayscale images).
/// </summary>
internal class WhiteIsZero4TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
/// <summary>
/// Implements the 'WhiteIsZero' photometric interpretation (optimised for 8-bit grayscale images).
/// Implements the 'WhiteIsZero' photometric interpretation (optimized for 8-bit grayscale images).
/// </summary>
internal class WhiteIsZero8TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>

5
src/ImageSharp/Formats/Tiff/README.md

@ -25,11 +25,6 @@
## Implementation Status
### Know issue which need to be fixed
Decoder:
- Decoding compressed images with HorizontalPrediction: Works for deflate, but not for lzw (maybe an issue with lzw itself?).
### Deviations from the TIFF spec (to be fixed)
- Decoder

6
src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs

@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
if (tiffMetadata.XmpProfile == null)
{
IExifValue<byte[]> val = frame.ExifProfile.GetValue<byte[]>(ExifTag.XMP);
IExifValue<byte[]> val = frame.ExifProfile.GetValue(ExifTag.XMP);
if (val != null)
{
tiffMetadata.XmpProfile = val.Value;
@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
if (coreMetadata.IptcProfile == null)
{
IExifValue<byte[]> val = frame.ExifProfile.GetValue<byte[]>(ExifTag.IPTC);
IExifValue<byte[]> val = frame.ExifProfile.GetValue(ExifTag.IPTC);
if (val != null)
{
coreMetadata.IptcProfile = new IptcProfile(val.Value);
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
if (coreMetadata.IccProfile == null)
{
IExifValue<byte[]> val = frame.ExifProfile.GetValue<byte[]>(ExifTag.IccProfile);
IExifValue<byte[]> val = frame.ExifProfile.GetValue(ExifTag.IccProfile);
if (val != null)
{
coreMetadata.IccProfile = new IccProfile(val.Value);

6
src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs

@ -29,14 +29,14 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
TiffThrowHelper.ThrowNotSupported("The lower-order bits of the byte FillOrder is not supported.");
}
if (entries.ExifProfile.GetValue<uint[]>(ExifTag.TileOffsets) != null)
if (entries.ExifProfile.GetValue(ExifTag.TileOffsets) != null)
{
TiffThrowHelper.ThrowNotSupported("The Tile images is not supported.");
TiffThrowHelper.ThrowNotSupported("Tiled images are not supported.");
}
if (entries.Predictor == TiffPredictor.FloatingPoint)
{
TiffThrowHelper.ThrowNotSupported("ImageSharp does not support FloatingPoint Predictor images.");
TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported.");
}
if (entries.SampleFormat != null)

20
src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs

@ -50,11 +50,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// </summary>
private readonly IQuantizer quantizer;
/// <summary>
/// Indicating whether to use horizontal prediction. This can improve the compression ratio with deflate compression.
/// </summary>
private readonly bool useHorizontalPredictor;
/// <summary>
/// Sets the deflate compression level.
/// </summary>
@ -71,7 +66,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
this.CompressionType = options.Compression;
this.Mode = options.Mode;
this.quantizer = options.Quantizer ?? KnownQuantizers.Octree;
this.useHorizontalPredictor = options.UseHorizontalPredictor;
this.UseHorizontalPredictor = options.UseHorizontalPredictor;
this.compressionLevel = options.CompressionLevel;
}
@ -90,7 +85,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// </summary>
internal TiffEncodingMode Mode { get; private set; }
internal bool UseHorizontalPredictor => this.useHorizontalPredictor;
/// <summary>
/// Gets a value indicating whether to use horizontal prediction. This can improve the compression ratio with deflate compression.
/// </summary>
internal bool UseHorizontalPredictor { get; }
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
@ -166,16 +164,16 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
switch (this.Mode)
{
case TiffEncodingMode.ColorPalette:
imageDataBytes = writer.WritePalettedRgb(image, this.quantizer, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor, entriesCollector);
imageDataBytes = writer.WritePalettedRgb(image, this.quantizer, this.CompressionType, this.compressionLevel, this.UseHorizontalPredictor, entriesCollector);
break;
case TiffEncodingMode.Gray:
imageDataBytes = writer.WriteGray(image, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor);
imageDataBytes = writer.WriteGray(image, this.CompressionType, this.compressionLevel, this.UseHorizontalPredictor);
break;
case TiffEncodingMode.BiColor:
imageDataBytes = writer.WriteBiColor(image, this.CompressionType, this.compressionLevel);
break;
default:
imageDataBytes = writer.WriteRgb(image, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor);
imageDataBytes = writer.WriteRgb(image, this.CompressionType, this.compressionLevel, this.UseHorizontalPredictor);
break;
}
@ -209,7 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
writer.Write((ushort)entries.Count);
foreach (ExifValue entry in entries)
foreach (IExifValue entry in entries)
{
writer.Write((ushort)entry.Tag);
writer.Write((ushort)entry.DataType);

6
src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs

@ -114,17 +114,17 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
var xResolution = new ExifRational(ExifTagValue.XResolution)
{
Value = frameMetadata.ExifProfile.GetValue<Rational>(ExifTag.XResolution).Value
Value = frameMetadata.ExifProfile.GetValue(ExifTag.XResolution).Value
};
var yResolution = new ExifRational(ExifTagValue.YResolution)
{
Value = frameMetadata.ExifProfile.GetValue<Rational>(ExifTag.YResolution).Value
Value = frameMetadata.ExifProfile.GetValue(ExifTag.YResolution).Value
};
var resolutionUnit = new ExifShort(ExifTagValue.ResolutionUnit)
{
Value = frameMetadata.ExifProfile.GetValue<ushort>(ExifTag.ResolutionUnit).Value
Value = frameMetadata.ExifProfile.GetValue(ExifTag.ResolutionUnit).Value
};
this.collector.AddInternal(xResolution);

54
src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs

@ -39,23 +39,27 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
internal set => this.frameTags = value;
}
/// <summary>Gets a general indication of the kind of data contained in this subfile.</summary>
/// <summary>
/// Gets a general indication of the kind of data contained in this subfile.
/// </summary>
/// <value>A general indication of the kind of data contained in this subfile.</value>
public TiffNewSubfileType SubfileType => (TiffNewSubfileType?)this.ExifProfile.GetValue<uint>(ExifTag.SubfileType)?.Value ?? TiffNewSubfileType.FullImage;
public TiffNewSubfileType SubfileType => (TiffNewSubfileType?)this.ExifProfile.GetValue(ExifTag.SubfileType)?.Value ?? TiffNewSubfileType.FullImage;
/// <summary>Gets a general indication of the kind of data contained in this subfile.</summary>
/// <summary>
/// Gets a general indication of the kind of data contained in this subfile.
/// </summary>
/// <value>A general indication of the kind of data contained in this subfile.</value>
public TiffSubfileType? OldSubfileType => (TiffSubfileType?)this.ExifProfile.GetValue<ushort>(ExifTag.OldSubfileType)?.Value;
public TiffSubfileType? OldSubfileType => (TiffSubfileType?)this.ExifProfile.GetValue(ExifTag.OldSubfileType)?.Value;
/// <summary>
/// Gets the number of columns in the image, i.e., the number of pixels per row.
/// </summary>
public Number Width => this.ExifProfile.GetValue<Number>(ExifTag.ImageWidth).Value;
public Number Width => this.ExifProfile.GetValue(ExifTag.ImageWidth).Value;
/// <summary>
/// Gets the number of rows of pixels in the image.
/// </summary>
public Number Height => this.ExifProfile.GetValue<Number>(ExifTag.ImageLength).Value;
public Number Height => this.ExifProfile.GetValue(ExifTag.ImageLength).Value;
/// <summary>
/// Gets the number of bits per component.
@ -64,7 +68,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
get
{
var bits = this.ExifProfile.GetValue<ushort[]>(ExifTag.BitsPerSample)?.Value;
var bits = this.ExifProfile.GetValue(ExifTag.BitsPerSample)?.Value;
if (bits == null)
{
if (this.PhotometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero
@ -96,19 +100,21 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
}
}
/// <summary>Gets the compression scheme used on the image data.</summary>
/// <summary>
/// Gets the compression scheme used on the image data.
/// </summary>
/// <value>The compression scheme used on the image data.</value>
public TiffCompression Compression => (TiffCompression)this.ExifProfile.GetValue<ushort>(ExifTag.Compression).Value;
public TiffCompression Compression => (TiffCompression)this.ExifProfile.GetValue(ExifTag.Compression).Value;
/// <summary>
/// Gets the color space of the image data.
/// </summary>
public TiffPhotometricInterpretation PhotometricInterpretation => (TiffPhotometricInterpretation)this.ExifProfile.GetValue<ushort>(ExifTag.PhotometricInterpretation).Value;
public TiffPhotometricInterpretation PhotometricInterpretation => (TiffPhotometricInterpretation)this.ExifProfile.GetValue(ExifTag.PhotometricInterpretation).Value;
/// <summary>
/// Gets the logical order of bits within a byte.
/// </summary>
internal TiffFillOrder FillOrder => (TiffFillOrder?)this.ExifProfile.GetValue<ushort>(ExifTag.FillOrder)?.Value ?? TiffFillOrder.MostSignificantBitFirst;
internal TiffFillOrder FillOrder => (TiffFillOrder?)this.ExifProfile.GetValue(ExifTag.FillOrder)?.Value ?? TiffFillOrder.MostSignificantBitFirst;
/// <summary>
/// Gets or sets the a string that describes the subject of the image.
@ -137,25 +143,29 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
set => this.ExifProfile.SetValue(ExifTag.Model, value);
}
/// <summary>Gets for each strip, the byte offset of that strip..</summary>
public Number[] StripOffsets => this.ExifProfile.GetValue<Number[]>(ExifTag.StripOffsets).Value;
/// <summary>
/// Gets for each strip, the byte offset of that strip.
/// </summary>
public Number[] StripOffsets => this.ExifProfile.GetValue(ExifTag.StripOffsets).Value;
/// <summary>
/// Gets the number of components per pixel.
/// </summary>
public ushort SamplesPerPixel => this.ExifProfile.GetValue<ushort>(ExifTag.SamplesPerPixel).Value;
public ushort SamplesPerPixel => this.ExifProfile.GetValue(ExifTag.SamplesPerPixel).Value;
/// <summary>
/// Gets the number of rows per strip.
/// </summary>
public Number RowsPerStrip => this.ExifProfile.GetValue<Number>(ExifTag.RowsPerStrip).Value;
public Number RowsPerStrip => this.ExifProfile.GetValue(ExifTag.RowsPerStrip).Value;
/// <summary>
/// Gets for each strip, the number of bytes in the strip after compression.
/// </summary>
public Number[] StripByteCounts => this.ExifProfile.GetValue<Number[]>(ExifTag.StripByteCounts).Value;
public Number[] StripByteCounts => this.ExifProfile.GetValue(ExifTag.StripByteCounts).Value;
/// <summary>Gets the resolution of the image in x- direction.</summary>
/// <summary>
/// Gets the resolution of the image in x- direction.
/// </summary>
/// <value>The density of the image in x- direction.</value>
public double? HorizontalResolution => this.GetResolution(ExifTag.XResolution);
@ -168,7 +178,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// <summary>
/// Gets how the components of each pixel are stored.
/// </summary>
public TiffPlanarConfiguration PlanarConfiguration => (TiffPlanarConfiguration?)this.ExifProfile.GetValue<ushort>(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration;
public TiffPlanarConfiguration PlanarConfiguration => (TiffPlanarConfiguration?)this.ExifProfile.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration;
/// <summary>
/// Gets the unit of measurement for XResolution and YResolution.
@ -214,12 +224,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// <summary>
/// Gets a color map for palette color images.
/// </summary>
public ushort[] ColorMap => this.ExifProfile.GetValue<ushort[]>(ExifTag.ColorMap)?.Value;
public ushort[] ColorMap => this.ExifProfile.GetValue(ExifTag.ColorMap)?.Value;
/// <summary>
/// Gets the description of extra components.
/// </summary>
public ushort[] ExtraSamples => this.ExifProfile.GetValue<ushort[]>(ExifTag.ExtraSamples)?.Value;
public ushort[] ExtraSamples => this.ExifProfile.GetValue(ExifTag.ExtraSamples)?.Value;
/// <summary>
/// Gets or sets the copyright notice.
@ -233,13 +243,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// <summary>
/// Gets a mathematical operator that is applied to the image data before an encoding scheme is applied.
/// </summary>
public TiffPredictor Predictor => (TiffPredictor?)this.ExifProfile.GetValue<ushort>(ExifTag.Predictor)?.Value ?? DefaultPredictor;
public TiffPredictor Predictor => (TiffPredictor?)this.ExifProfile.GetValue(ExifTag.Predictor)?.Value ?? DefaultPredictor;
/// <summary>
/// Gets the specifies how to interpret each data sample in a pixel.
/// <see cref="SamplesPerPixel"/>
/// </summary>
public TiffSampleFormat[] SampleFormat => this.ExifProfile.GetValue<ushort[]>(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray();
public TiffSampleFormat[] SampleFormat => this.ExifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray();
/// <summary>
/// Clears the metadata.

40
src/ImageSharp/Formats/Tiff/TiffFrameMetadataResolutionExtensions.cs

@ -37,14 +37,14 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
public static PixelResolutionUnit GetResolutionUnit(this TiffFrameMetadata meta)
{
ushort res = meta.ExifProfile.GetValue<ushort>(ExifTag.ResolutionUnit)?.Value ?? TiffFrameMetadata.DefaultResolutionUnit;
ushort res = meta.ExifProfile.GetValue(ExifTag.ResolutionUnit)?.Value ?? TiffFrameMetadata.DefaultResolutionUnit;
return (PixelResolutionUnit)(res - 1);
}
public static double? GetResolution(this TiffFrameMetadata meta, ExifTag<Rational> tag)
{
IExifValue<Rational> resolution = meta.ExifProfile.GetValue<Rational>(tag);
IExifValue<Rational> resolution = meta.ExifProfile.GetValue(tag);
if (resolution == null)
{
return null;
@ -73,27 +73,25 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
meta.ExifProfile.RemoveValue(tag);
return;
}
else
{
double res = value.Value;
switch (meta.ResolutionUnit)
{
case PixelResolutionUnit.AspectRatio:
res = 0;
break;
case PixelResolutionUnit.PixelsPerCentimeter:
res = UnitConverter.InchToCm(res);
break;
case PixelResolutionUnit.PixelsPerMeter:
res = UnitConverter.InchToMeter(res);
break;
case PixelResolutionUnit.PixelsPerInch:
default:
break;
}
meta.ExifProfile.SetValue(tag, new Rational(res));
double res = value.Value;
switch (meta.ResolutionUnit)
{
case PixelResolutionUnit.AspectRatio:
res = 0;
break;
case PixelResolutionUnit.PixelsPerCentimeter:
res = UnitConverter.InchToCm(res);
break;
case PixelResolutionUnit.PixelsPerMeter:
res = UnitConverter.InchToMeter(res);
break;
case PixelResolutionUnit.PixelsPerInch:
default:
break;
}
meta.ExifProfile.SetValue(tag, new Rational(res));
}
}
}

33
src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
@ -17,40 +16,16 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// </summary>
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowImageFormatException(string errorMessage)
=> throw new ImageFormatException(errorMessage);
public static void ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage);
[MethodImpl(InliningOptions.ColdPath)]
public static Exception TagNotFound(string tagName)
=> new ArgumentException("Required tag is not found.", tagName);
public static Exception NotSupportedCompression(string compressionType) => throw new NotSupportedException($"Not supported compression: {compressionType}");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowTagNotFound(string tagName)
=> throw TagNotFound(tagName);
public static Exception InvalidColorType(string colorType) => throw new NotSupportedException($"Invalid color type: {colorType}");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadZlibHeader(int cmf) => throw new ImageFormatException($"Bad compression method for ZLIB header: cmf={cmf}");
[MethodImpl(InliningOptions.ColdPath)]
public static Exception NotSupportedCompression(string compressionType) => new NotSupportedException("Not supported compression: " + compressionType);
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNotSupportedCompression(string compressionType) => throw NotSupportedCompression(compressionType);
[MethodImpl(InliningOptions.ColdPath)]
public static Exception InvalidColorType(string colorType) => new NotSupportedException("Invalid color type: " + colorType);
[MethodImpl(InliningOptions.ColdPath)]
public static Exception InvalidHeader() => new ImageFormatException("Invalid TIFF file header.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowInvalidHeader() => throw InvalidHeader();
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowOutOfRange(string structure) => throw new InvalidDataException($"Out of range of {structure} structure.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadStringEntry() => throw new ImageFormatException("The retrieved string is not null terminated.");
public static Exception ThrowInvalidHeader() => throw new ImageFormatException("Invalid TIFF file header.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNotSupported(string message) => throw new NotSupportedException(message);

19
src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs

@ -69,19 +69,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// Writes an array of bytes to the current stream.
/// </summary>
/// <param name="value">The bytes to write.</param>
public void Write(byte[] value)
{
this.output.Write(value, 0, value.Length);
}
public void Write(byte[] value) => this.output.Write(value, 0, value.Length);
/// <summary>
/// Writes a byte to the current stream.
/// </summary>
/// <param name="value">The byte to write.</param>
public void Write(byte value)
{
this.output.Write(new byte[] { value }, 0, 1);
}
public void Write(byte value) => this.output.Write(new[] { value }, 0, 1);
/// <summary>
/// Writes a two-byte unsigned integer to the current stream.
@ -258,7 +252,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
where TPixel : unmanaged, IPixel<TPixel>
{
// Worst case is that the actual compressed data is larger then the input data. In this case we need 1 additional byte per 127 bytes.
int additionalBytes = ((image.Width * 3) / 127) + 1;
int additionalBytes = (image.Width * 3 / 127) + 1;
using IManagedByteBuffer compressedRow = this.memoryAllocator.AllocateManagedByteBuffer((image.Width * 3) + additionalBytes, AllocationOptions.Clean);
Span<byte> compressedRowSpan = compressedRow.GetSpan();
int bytesWritten = 0;
@ -464,7 +458,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
where TPixel : unmanaged, IPixel<TPixel>
{
// Worst case is that the actual compressed data is larger then the input data. In this case we need 1 additional byte per 127 bytes.
int additionalBytes = ((image.Width * 3) / 127) + 1;
int additionalBytes = (image.Width * 3 / 127) + 1;
using IManagedByteBuffer compressedRow = this.memoryAllocator.AllocateManagedByteBuffer((image.Width * 3) + additionalBytes, AllocationOptions.Clean);
Span<byte> compressedRowSpan = compressedRow.GetSpan();
@ -806,9 +800,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// <summary>
/// Disposes <see cref="TiffWriter"/> instance, ensuring any unwritten data is flushed.
/// </summary>
public void Dispose()
{
this.output.Flush();
}
public void Dispose() => this.output.Flush();
}
}

Loading…
Cancel
Save