Browse Source

Standardize EXIF dimension transform updates

pull/448/head
James Jackson-South 8 years ago
parent
commit
d2df29e4b4
  1. 4
      src/ImageSharp/DefaultInternalImageProcessorContext.cs
  2. 6
      src/ImageSharp/Processing/Processors/CloningImageProcessor.cs
  3. 2
      src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
  4. 4
      src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
  5. 24
      src/ImageSharp/Processing/Processors/Transforms/InterpolatedTransformProcessorBase.cs
  6. 2
      src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
  7. 2
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs
  8. 20
      src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs
  9. 34
      src/ImageSharp/Processing/Transforms/TransformHelpers.cs

4
src/ImageSharp/DefaultInternalImageProcessorContext.cs

@ -52,8 +52,8 @@ namespace SixLabors.ImageSharp
if (!this.mutate && this.destination == null)
{
// This will only work if the first processor applied is the cloning one thus
// realistically for this optermissation to work the resize must the first processor
// applied any only up processors will take the douple data path.
// realistically for this optimization to work the resize must the first processor
// applied any only up processors will take the double data path.
if (processor is ICloningImageProcessor<TPixel> cloningImageProcessor)
{
this.destination = cloningImageProcessor.CloneAndApply(this.source, rectangle);

6
src/ImageSharp/Processing/Processors/CloningImageProcessor.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing
if (clone.Frames.Count != source.Frames.Count)
{
throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. The processor changed the number of frames.");
throw new ImageProcessingException($"An error occurred when processing the image using {this.GetType().Name}. The processor changed the number of frames.");
}
Configuration configuration = source.GetConfiguration();
@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.Processing
// we now need to move the pixel data/size data from one image base to another
if (cloned.Frames.Count != source.Frames.Count)
{
throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. The processor changed the number of frames.");
throw new ImageProcessingException($"An error occurred when processing the image using {this.GetType().Name}. The processor changed the number of frames.");
}
source.SwapPixelsBuffers(cloned);
@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Processing
}
/// <summary>
/// Generates a deep clone of the source image that operatinos should be applied to.
/// Generates a deep clone of the source image that operations should be applied to.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">The source rectangle.</param>

2
src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs

@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public AffineTransformProcessor(Matrix3x2 matrix, IResampler sampler, Size targetDimensions)
: base(sampler)
{
// Tansforms are inverted else the output is the opposite of the expected.
// Transforms are inverted else the output is the opposite of the expected.
Matrix3x2.Invert(matrix, out matrix);
this.TransformMatrix = matrix;
this.targetDimensions = targetDimensions;

4
src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs

@ -60,5 +60,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
source.SwapPixelsBuffers(targetPixels);
}
}
/// <inheritdoc/>
protected override void AfterImageApply(Image<TPixel> source, Rectangle sourceRectangle)
=> TransformHelpers.UpdateDimensionalMetData(source);
}
}

24
src/ImageSharp/Processing/Processors/Transforms/InterpolatedTransformProcessorBase.cs

@ -3,9 +3,7 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors
{
@ -13,7 +11,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// The base class for performing interpolated affine and non-affine transforms.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal abstract class InterpolatedTransformProcessorBase<TPixel> : CloningImageProcessor<TPixel>
internal abstract class InterpolatedTransformProcessorBase<TPixel> : TransformProcessorBase<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
@ -115,25 +113,5 @@ namespace SixLabors.ImageSharp.Processing.Processors
return (MathF.Ceiling(scale * this.Sampler.Radius), scale, ratio);
}
/// <inheritdoc/>
protected override void AfterImageApply(Image<TPixel> source, Image<TPixel> destination, Rectangle sourceRectangle)
{
ExifProfile profile = destination.MetaData.ExifProfile;
if (profile == null)
{
return;
}
if (profile.GetValue(ExifTag.PixelXDimension) != null)
{
profile.SetValue(ExifTag.PixelXDimension, destination.Width);
}
if (profile.GetValue(ExifTag.PixelYDimension) != null)
{
profile.SetValue(ExifTag.PixelYDimension, destination.Height);
}
}
}
}

2
src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs

@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public ProjectiveTransformProcessor(Matrix4x4 matrix, IResampler sampler, Rectangle rectangle)
: base(sampler)
{
// Tansforms are inverted else the output is the opposite of the expected.
// Transforms are inverted else the output is the opposite of the expected.
Matrix4x4.Invert(matrix, out matrix);
this.TransformMatrix = matrix;
this.targetRectangle = rectangle;

2
src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// Adapted from <see href="http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/filter_rcg.c"/>
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal abstract class ResamplingWeightedProcessor<TPixel> : CloningImageProcessor<TPixel>
internal abstract class ResamplingWeightedProcessor<TPixel> : TransformProcessorBase<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>

20
src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs

@ -0,0 +1,20 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors
{
/// <summary>
/// The base class for all transform processors. Any processor that changes the dimensions of the image should inherit from this.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal abstract class TransformProcessorBase<TPixel> : CloningImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <inheritdoc/>
protected override void AfterImageApply(Image<TPixel> source, Image<TPixel> destination, Rectangle sourceRectangle)
=> TransformHelpers.UpdateDimensionalMetData(destination);
}
}

34
src/ImageSharp/Processing/Transforms/TransformHelpers.cs

@ -3,6 +3,8 @@
using System;
using System.Numerics;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp
@ -12,6 +14,38 @@ namespace SixLabors.ImageSharp
/// </summary>
internal class TransformHelpers
{
/// <summary>
/// Updates the dimensional metadata of a transformed image
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The image to update</param>
public static void UpdateDimensionalMetData<TPixel>(Image<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
ExifProfile profile = image.MetaData.ExifProfile;
if (profile == null)
{
return;
}
// Removing the previously stored value allows us to set a value with our own data tag if required.
if (profile.GetValue(ExifTag.PixelXDimension) != null)
{
profile.RemoveValue(ExifTag.PixelXDimension);
profile.SetValue(
ExifTag.PixelXDimension,
image.Width <= ushort.MaxValue ? (ushort)image.Width : (uint)image.Width);
}
if (profile.GetValue(ExifTag.PixelYDimension) != null)
{
profile.RemoveValue(ExifTag.PixelYDimension);
profile.SetValue(
ExifTag.PixelYDimension,
image.Height <= ushort.MaxValue ? (ushort)image.Height : (uint)image.Height);
}
}
/// <summary>
/// Returns the bounding <see cref="Rectangle"/> relative to the source for the given transformation matrix.
/// </summary>

Loading…
Cancel
Save