Browse Source

Remove TiffFrameMetadataResolutionExtensions class

pull/1570/head
Ildar Khayrutdinov 5 years ago
parent
commit
f9570d37f7
  1. 50
      src/ImageSharp/Common/Helpers/UnitConverter.cs
  2. 78
      src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
  3. 48
      src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs
  4. 97
      src/ImageSharp/Formats/Tiff/TiffFrameMetadataResolutionExtensions.cs
  5. 6
      src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter.cs
  6. 2
      src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter.cs
  7. 1
      tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
  8. 2
      tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs

50
src/ImageSharp/Common/Helpers/UnitConverter.cs

@ -30,6 +30,11 @@ namespace SixLabors.ImageSharp.Common.Helpers
/// </summary>
private const double InchesInMeter = 1 / 0.0254D;
/// <summary>
/// The default resolution unit value.
/// </summary>
private const PixelResolutionUnit DefaultResolutionUnit = PixelResolutionUnit.PixelsPerInch;
/// <summary>
/// Scales the value from centimeters to meters.
/// </summary>
@ -89,7 +94,50 @@ namespace SixLabors.ImageSharp.Common.Helpers
IExifValue<ushort> resolution = profile.GetValue(ExifTag.ResolutionUnit);
// EXIF is 1, 2, 3 so we minus "1" off the result.
return resolution is null ? default : (PixelResolutionUnit)(byte)(resolution.Value - 1);
return resolution is null ? DefaultResolutionUnit : (PixelResolutionUnit)(byte)(resolution.Value - 1);
}
/// <summary>
/// Sets the exif profile resolution values.
/// </summary>
/// <param name="exifProfile">The exif profile.</param>
/// <param name="unit">The resolution unit.</param>
/// <param name="horizontal">The horizontal resolution value.</param>
/// <param name="vertical">The vertical resolution value.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void SetResolutionValues(ExifProfile exifProfile, PixelResolutionUnit unit, double horizontal, double vertical)
{
switch (unit)
{
case PixelResolutionUnit.AspectRatio:
case PixelResolutionUnit.PixelsPerInch:
case PixelResolutionUnit.PixelsPerCentimeter:
break;
case PixelResolutionUnit.PixelsPerMeter:
{
unit = PixelResolutionUnit.PixelsPerCentimeter;
horizontal = UnitConverter.MeterToCm(horizontal);
vertical = UnitConverter.MeterToCm(vertical);
}
break;
default:
unit = PixelResolutionUnit.PixelsPerInch;
break;
}
exifProfile.SetValue(ExifTag.ResolutionUnit, (ushort)(unit + 1));
if (unit == PixelResolutionUnit.AspectRatio)
{
exifProfile.RemoveValue(ExifTag.XResolution);
exifProfile.RemoveValue(ExifTag.YResolution);
}
else
{
exifProfile.SetValue(ExifTag.XResolution, new Rational(horizontal));
exifProfile.SetValue(ExifTag.YResolution, new Rational(vertical));
}
}
}
}

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

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
@ -12,6 +12,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
internal class TiffEncoderEntriesCollector
{
private const string SoftwareValue = "ImageSharp";
public List<IExifValue> Entries { get; } = new List<IExifValue>();
public void ProcessGeneral<TPixel>(Image<TPixel> image)
@ -21,18 +23,20 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
public void ProcessImageFormat(TiffEncoderCore encoder)
=> new ImageFormatProcessor(this).Process(encoder);
public void Add(IExifValue entry)
public void AddOrReplace(IExifValue entry)
{
IExifValue exist = this.Entries.Find(t => t.Tag == entry.Tag);
if (exist != null)
int index = this.Entries.FindIndex(t => t.Tag == entry.Tag);
if (index >= 0)
{
this.Entries.Remove(exist);
this.Entries[index] = entry;
}
else
{
this.Entries.Add(entry);
}
this.Entries.Add(entry);
}
private void AddInternal(IExifValue entry) => this.Entries.Add(entry);
private void Add(IExifValue entry) => this.Entries.Add(entry);
private class GeneralProcessor
{
@ -57,12 +61,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
var software = new ExifString(ExifTagValue.Software)
{
Value = "ImageSharp"
Value = SoftwareValue
};
this.collector.AddInternal(width);
this.collector.AddInternal(height);
this.collector.AddInternal(software);
this.collector.Add(width);
this.collector.Add(height);
this.collector.Add(software);
this.ProcessResolution(image.Metadata, frameMetadata);
@ -70,7 +74,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
this.ProcessMetadata(frameMetadata);
}
private static bool IsMetadata(ExifTag tag)
private static bool IsPureMetadata(ExifTag tag)
{
switch ((ExifTagValue)(ushort)tag)
{
@ -107,29 +111,22 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
private void ProcessResolution(ImageMetadata imageMetadata, TiffFrameMetadata frameMetadata)
{
frameMetadata.SetResolutions(
UnitConverter.SetResolutionValues(
frameMetadata.ExifProfile,
imageMetadata.ResolutionUnits,
imageMetadata.HorizontalResolution,
imageMetadata.VerticalResolution);
var xResolution = new ExifRational(ExifTagValue.XResolution)
{
Value = frameMetadata.ExifProfile.GetValue(ExifTag.XResolution).Value
};
this.collector.Add(frameMetadata.ExifProfile.GetValue(ExifTag.ResolutionUnit).DeepClone());
var yResolution = new ExifRational(ExifTagValue.YResolution)
{
Value = frameMetadata.ExifProfile.GetValue(ExifTag.YResolution).Value
};
IExifValue xResolution = frameMetadata.ExifProfile.GetValue(ExifTag.XResolution)?.DeepClone();
IExifValue yResolution = frameMetadata.ExifProfile.GetValue(ExifTag.YResolution)?.DeepClone();
var resolutionUnit = new ExifShort(ExifTagValue.ResolutionUnit)
if (xResolution != null && yResolution != null)
{
Value = frameMetadata.ExifProfile.GetValue(ExifTag.ResolutionUnit).Value
};
this.collector.AddInternal(xResolution);
this.collector.AddInternal(yResolution);
this.collector.AddInternal(resolutionUnit);
this.collector.Add(xResolution);
this.collector.Add(yResolution);
}
}
private void ProcessMetadata(TiffFrameMetadata frameMetadata)
@ -160,7 +157,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
break;
case ExifParts.IfdTags:
if (!IsMetadata(entry.Tag))
if (!IsPureMetadata(entry.Tag))
{
continue;
}
@ -170,7 +167,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
if (!this.collector.Entries.Exists(t => t.Tag == entry.Tag))
{
this.collector.AddInternal(entry.DeepClone());
this.collector.AddOrReplace(entry.DeepClone());
}
}
}
@ -194,7 +191,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
Value = imageMetadata.IptcProfile.Data
};
this.collector.AddInternal(iptc);
this.collector.Add(iptc);
}
else
{
@ -208,7 +205,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
Value = imageMetadata.IccProfile.ToByteArray()
};
this.collector.AddInternal(icc);
this.collector.Add(icc);
}
else
{
@ -223,7 +220,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
Value = tiffMetadata.XmpProfile
};
this.collector.AddInternal(xmp);
this.collector.Add(xmp);
}
else
{
@ -262,10 +259,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
Value = (ushort)encoder.PhotometricInterpretation
};
this.collector.Add(samplesPerPixel);
this.collector.Add(bitPerSample);
this.collector.Add(compression);
this.collector.Add(photometricInterpretation);
this.collector.AddOrReplace(samplesPerPixel);
this.collector.AddOrReplace(bitPerSample);
this.collector.AddOrReplace(compression);
this.collector.AddOrReplace(photometricInterpretation);
if (encoder.UseHorizontalPredictor)
{
@ -273,7 +270,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
var predictor = new ExifShort(ExifTagValue.Predictor) { Value = (ushort)TiffPredictor.Horizontal };
this.collector.Add(predictor);
this.collector.AddOrReplace(predictor);
}
}
}
@ -282,12 +279,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
switch (encoder.PhotometricInterpretation)
{
case TiffPhotometricInterpretation.Rgb:
return 3;
case TiffPhotometricInterpretation.PaletteColor:
case TiffPhotometricInterpretation.BlackIsZero:
case TiffPhotometricInterpretation.WhiteIsZero:
return 1;
case TiffPhotometricInterpretation.Rgb:
default:
return 3;
}

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

@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants;
using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Metadata;
@ -15,9 +16,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// </summary>
public class TiffFrameMetadata : IDeepCloneable
{
// 2 (Inch)
internal const ushort DefaultResolutionUnit = 2;
private const TiffPlanarConfiguration DefaultPlanarConfiguration = TiffPlanarConfiguration.Chunky;
private const TiffPredictor DefaultPredictor = TiffPredictor.None;
@ -212,13 +210,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// 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);
public double? HorizontalResolution => this.ExifProfile.GetValue(ExifTag.XResolution)?.Value.ToDouble();
/// <summary>
/// Gets the resolution of the image in y- direction.
/// </summary>
/// <value>The density of the image in y- direction.</value>
public double? VerticalResolution => this.GetResolution(ExifTag.YResolution);
public double? VerticalResolution => this.ExifProfile.GetValue(ExifTag.YResolution)?.Value.ToDouble();
/// <summary>
/// Gets how the components of each pixel are stored.
@ -228,7 +226,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// <summary>
/// Gets the unit of measurement for XResolution and YResolution.
/// </summary>
public PixelResolutionUnit ResolutionUnit => this.GetResolutionUnit();
public PixelResolutionUnit ResolutionUnit => UnitConverter.ExifProfileToResolutionUnit(this.ExifProfile);
/// <summary>
/// Gets a color map for palette color images.
@ -252,28 +250,16 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
public TiffSampleFormat[] SampleFormat => this.ExifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray();
/// <summary>
/// Clears the metadata.
/// Clears the pure metadata.
/// </summary>
public void ClearMetadata()
{
var tags = new List<IExifValue>();
foreach (IExifValue entry in this.ExifProfile.Values)
{
switch ((ExifTagValue)(ushort)entry.Tag)
if (IsFormatTag((ExifTagValue)(ushort)entry.Tag))
{
case ExifTagValue.ImageWidth:
case ExifTagValue.ImageLength:
case ExifTagValue.ResolutionUnit:
case ExifTagValue.XResolution:
case ExifTagValue.YResolution:
//// image format tags
case ExifTagValue.Predictor:
case ExifTagValue.PlanarConfiguration:
case ExifTagValue.PhotometricInterpretation:
case ExifTagValue.BitsPerSample:
case ExifTagValue.ColorMap:
tags.Add(entry);
break;
tags.Add(entry);
}
}
@ -282,5 +268,25 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// <inheritdoc/>
public IDeepCloneable DeepClone() => new TiffFrameMetadata() { ExifProfile = this.ExifProfile.DeepClone() };
private static bool IsFormatTag(ExifTagValue tag)
{
switch (tag)
{
case ExifTagValue.ImageWidth:
case ExifTagValue.ImageLength:
case ExifTagValue.ResolutionUnit:
case ExifTagValue.XResolution:
case ExifTagValue.YResolution:
case ExifTagValue.Predictor:
case ExifTagValue.PlanarConfiguration:
case ExifTagValue.PhotometricInterpretation:
case ExifTagValue.BitsPerSample:
case ExifTagValue.ColorMap:
return true;
}
return false;
}
}
}

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

@ -1,97 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
{
internal static class TiffFrameMetadataResolutionExtensions
{
public static void SetResolutions(this TiffFrameMetadata meta, PixelResolutionUnit unit, double horizontal, double vertical)
{
switch (unit)
{
case PixelResolutionUnit.AspectRatio:
case PixelResolutionUnit.PixelsPerInch:
case PixelResolutionUnit.PixelsPerCentimeter:
break;
case PixelResolutionUnit.PixelsPerMeter:
{
unit = PixelResolutionUnit.PixelsPerCentimeter;
horizontal = UnitConverter.MeterToCm(horizontal);
vertical = UnitConverter.MeterToCm(vertical);
}
break;
default:
unit = PixelResolutionUnit.PixelsPerInch;
break;
}
meta.ExifProfile.SetValue(ExifTag.ResolutionUnit, (ushort)(unit + 1));
meta.SetResolution(ExifTag.XResolution, horizontal);
meta.SetResolution(ExifTag.YResolution, vertical);
}
public static PixelResolutionUnit GetResolutionUnit(this TiffFrameMetadata meta)
{
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(tag);
if (resolution == null)
{
return null;
}
double res = resolution.Value.ToDouble();
switch (meta.ResolutionUnit)
{
case PixelResolutionUnit.AspectRatio:
return 0;
case PixelResolutionUnit.PixelsPerCentimeter:
return UnitConverter.CmToInch(res);
case PixelResolutionUnit.PixelsPerMeter:
return UnitConverter.MeterToInch(res);
case PixelResolutionUnit.PixelsPerInch:
default:
// DefaultResolutionUnit is Inch
return res;
}
}
private static void SetResolution(this TiffFrameMetadata meta, ExifTag<Rational> tag, double? value)
{
if (value == null)
{
meta.ExifProfile.RemoveValue(tag);
return;
}
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));
}
}
}

6
src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter.cs

@ -87,17 +87,17 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Writers
/// <param name="stripByteCounts">The strip byte counts.</param>
private void AddStripTags(int rowsPerStrip, uint[] stripOffsets, uint[] stripByteCounts)
{
this.EntriesCollector.Add(new ExifLong(ExifTagValue.RowsPerStrip)
this.EntriesCollector.AddOrReplace(new ExifLong(ExifTagValue.RowsPerStrip)
{
Value = (uint)rowsPerStrip
});
this.EntriesCollector.Add(new ExifLongArray(ExifTagValue.StripOffsets)
this.EntriesCollector.AddOrReplace(new ExifLongArray(ExifTagValue.StripOffsets)
{
Value = stripOffsets
});
this.EntriesCollector.Add(new ExifLongArray(ExifTagValue.StripByteCounts)
this.EntriesCollector.AddOrReplace(new ExifLongArray(ExifTagValue.StripByteCounts)
{
Value = stripByteCounts
});

2
src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter.cs

@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Writers
Value = palette
};
this.EntriesCollector.Add(colorMap);
this.EntriesCollector.AddOrReplace(colorMap);
}
}
}

1
tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs

@ -93,7 +93,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(expectedBitsPerPixel, meta.BitsPerPixel);
}
[Theory]
[WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncoderCompression.CcittGroup3Fax, TiffCompression.CcittGroup3Fax)]
[WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncoderCompression.ModifiedHuffman, TiffCompression.Ccitt1D)]

2
tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs

@ -198,10 +198,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(1, frame.SamplesPerPixel);
Assert.Equal(32u, frame.RowsPerStrip);
Assert.Equal(new Number[] { 297u }, frame.StripByteCounts, new NumberComparer());
Assert.Equal(PixelResolutionUnit.PixelsPerInch, frame.ResolutionUnit);
Assert.Equal(10, frame.HorizontalResolution);
Assert.Equal(10, frame.VerticalResolution);
Assert.Equal(TiffPlanarConfiguration.Chunky, frame.PlanarConfiguration);
Assert.Equal(PixelResolutionUnit.PixelsPerInch, frame.ResolutionUnit);
Assert.Equal("IrfanView", frame.ExifProfile.GetValue(ExifTag.Software).Value);
Assert.Null(frame.ExifProfile.GetValue(ExifTag.DateTime)?.Value);
Assert.Equal("This is author1;Author2", frame.ExifProfile.GetValue(ExifTag.Artist).Value);

Loading…
Cancel
Save